int pre[maxn];
int Find(int a){
int root = a;
while(root != pre[root]){
root = pre[root];
}
while(a != pre[a]){
int tmp = pre[a];
pre[a] = root;
a = tmp;
}
return root;
}
int pre[maxn];
int Find(int a){
if(a == pre[a]) return a;
return pre[a] = Find(pre[a]);
}
void Union(int a, int b){
int x = Find(a);
int y = Find(b);
if(x != y){
pre[x] = y;
}
}
例题:
POJ2236
题意
有一个计算机网络的所有线路都坏了,网络中有n台计算机,现在你可以做两种操作,修理(O)或者检测两台计算机是否连通(S),只有修理好的计算机才能连通。连通有个规则,两台计算机的距离不能超过给定的最大距离D(一开始会给你n台计算机的坐标)。检测的时候输出两台计算机是否能连通。
思路
每次修理好一台计算机的时候就遍历一下所有修好的计算机,看距离是否<=D,如果符合说明可以连通,将两台计算机所在集合合并。每次检查的时候判断一下这两台计算机是否在同一集合中即可。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 1005;
struct pot{
int x, y;
int re;
}p[maxn];
int pre[maxn];
double dis(pot a, pot b){
double res = sqrt(pow((double)abs(a.x - b.x), 2) + pow((double)abs(a.y - b.y), 2));
return res;
}
int Find(int a){
int root = a;
while(root != pre[root]){
root = pre[root];
}
while(a != pre[a]){
int tmp = pre[a];
pre[a] = root;
a = tmp;
}
return root;
}
void Union(int a, int b){
int x = Find(a);
int y = Find(b);
if(x != y){
pre[x] = y;
}
}
int main()
{
int n, d;
cin >> n >> d;
for(int i = 1; i <= n; i++){
cin >> p[i].x >> p[i].y;
pre[i] = i;
}
char c;
int pos, a, b;
while(cin >> c){
if(c == 'O'){
cin >> pos;
p[pos].re = 1;
for(int i = 1; i <= n; i++){
if(p[i].re == 1){
if(dis(p[i], p[pos]) <= (double)d){
Union(i, pos);
}
}
}
}
else if(c == 'S'){
cin >> a >> b;
if(Find(a) == Find(b)){
cout << "SUCCESS" << endl;
}
else cout << "FAIL" << endl;
}
}
return 0;
}