北大ACM2236——Wireless Network~~并查集

这一题,题目的大概意思是:有N台电脑,彼此直接能通信的最大距离为T,这些电脑因为地震损坏了,需要修理。修理之后,就可以跟其他的修理过的距离小于等于T的电脑通信,你需要回答的是某两台电脑是否能够通信。

简单的并查集的应用,只是加了一个限制条件。

输入N和T,下面N行为N个电脑的坐标。

再下面的是一直到文件结尾,输入O k,表示k电脑进行修理。输入S i j ,表示问你这两台电脑是否能够通信。

我用一个dis数组来存每两台电脑之间的距离,方便后面的判断。

下面是AC的代码,有详细的注释:

#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;

double dis[1005][1005];               //每台电脑与其他电脑之间的距离数组
int par[1005];                        //并查集
bool vis[1005];                       //标记该电脑是否已经修理过
int x[1005], y[1005];
int N, T;

int finds(int x)                     //并查集查找函数
{
	if(x == par[x])
		return x;
	else
		return par[x] = finds(par[x]);
}
void join(int x, int y)             //并查集合并函数
{
	x = finds(x);
	y = finds(y);
	if(x != y)
		par[y] = x;
}
int main()
{
//	freopen("data.txt", "r", stdin);
	int i, j, k, a , b;
	char str;
	scanf("%d%d", &N, &T);
	for(i = 1; i <= N; i++)                     //输入每台电脑坐标
	{
		scanf("%d%d", &x[i], &y[i]);
		par[i] = i;                             //初始化并查集
		vis[i] = false;                         //标记为没有修理过
	}
	getchar();
	for(i = 1; i <= N; i++)                     //计算每两台电脑直接的距离
	{
		for(j = 1; j <= i; j++)
		{
			if(i == j)
				dis[i][j] = 0.0;
			else
				dis[i][j] = dis[j][i] = sqrt(double((x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j])));
		}
	}
	while(scanf("%c", &str) != EOF)
	{	
		if(str == 'O')                         //输入的是 O,要进行修理
		{
			scanf("%d", &k);
			getchar();
			for(i = 1; i <= N; i++)            //与修理过的电脑之间距离的判断,判断是否能通信
			{
				if(i != k && vis[i] && dis[k][i] <= (double)T)
				{
					join(i, k);                //能就合并
				}
			}
			vis[k] = true;                     //标记为修理过
		}
		else if(str == 'S')                    //判断是否能通信
		{
			scanf("%d%d", &a, &b);
			getchar();
			if(finds(a) == finds(b))           //属于同一个并查集,就可以
				printf("SUCCESS\n");
			else
				printf("FAIL\n");
		}
	}
	return 0;
}


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。