PKU 2236 Wireless Network(并查集)

 

http://acm.pku.edu.cn/JudgeOnline/problem?id=2236

 

题目大意:亚洲海底地震,使得所有的电脑都坏了并中断了联系,现在有一群维修人员被派往现场修复。他们在那边会做两件事,1.“O”代表要修复某编号的电脑,“S”代表要测试两台编号不同的电脑是否可以连通,测试成功,则输出成功,否则失败。但是两台电脑之间如果要直接连通的话,它们之间的距离不能够超过OJ提供的距离D,如果超过的话,他们要连通的话,中间就要有中介电脑才行。现在你的工作就是根据修复人员所做的操作,输出成功或者失败。

 

解题思路:这道的话就是属于互通的题目啦,也就是要用到并查集。修复一台电脑就标记为修复过了,然后跟其他已经修复过的电脑进行合并,但是合并的条件必须是两台电脑的距离小于D。当要测试两台电脑时,就是判断他们的根结点是否一样或者是距离小于D,然后再进行合并。

 

#include <iostream> #include <math.h> using namespace std; #define size 1002 int parents[size]; int deep[size]; bool visited[size]; struct coordinate { double x; double y; }locate[size]; void CreateSet(int x)//创建集合 { parents[x] = x; deep[x] = 1; visited[x] = false; } int Find(int x)//寻找根结点 { int r = x; int temp; while(r!=parents[r]) r = parents[r]; while (x!=r) { temp = parents[x]; parents[temp] = r; x = temp; } return r; } void Union(int a,int b)//合并集合 { int t1 = Find(a); int t2 = Find(b); if(deep[t1]>deep[t2]) parents[t2] = t1; else parents[t1] = t2; if(deep[t1] == deep[t2]) deep[t2]++; } bool IsOk(int a,int b,long distance)//判断两台电脑是否可以连通 { double k; k = sqrt((locate[a].x-locate[b].x)*(locate[a].x-locate[b].x)+(locate[a].y-locate[b].y)*(locate[a].y-locate[b].y)); if(k<=distance) return true; else return false; } int main() { char commander; int computer; int p1,p2; int i; long distance; cin>>computer>>distance; for(i=1;i<=computer;i++) CreateSet(i); for (i=1;i<=computer;i++) cin>>locate[i].x>>locate[i].y; while (cin>>commander) { if (commander == 'O') { cin>>p1; visited[p1] = true; /*查看修复的电脑是否可以加入到并查集中*/ for(i=1;i<=computer;i++) { if(visited[i]&&i!=p1) if(IsOk(p1,i,distance)) if(Find(p1)!=Find(i)) Union(p1,i); } } else { cin>>p1>>p2; if(IsOk(p1,p2,distance)||Find(p1)==Find(p2)) { cout<<"SUCCESS"<<endl; if(Find(p1)!=Find(p2)) Union(p1,p2); } else cout<<"FAIL"<<endl; } } return 0; }

你可能感兴趣的:(PKU 2236 Wireless Network(并查集))