这一题,题目的大概意思是:有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;
}