并查集–Wireless Network
Description
东南亚发生地震。亚洲合作医疗队(ACM)已经与LAP计算机建立了无线网络,但一次意外的余震袭击,网络中的所有计算机都被破坏了。计算机被一个接一个地修理,网络逐渐又开始工作了。由于硬件的限制,每台计算机只能与距离它不超过d米的计算机直接通信。但是,每台计算机都可以看作是另外两台计算机之间通信的中介,也就是说,如果计算机A和计算机B可以直接通信,或者计算机C可以与A和B同时通信,那么计算机A和计算机B就可以通信。
在修复网络的过程中,工人可以随时进行两种操作,修复一台计算机,或者测试两台计算机是否能通信。你的工作是回答所有的测试操作。
Input
第一行包含两个整数N和d(1<=N<=1001,0<=d<=20000)。这里N是计算机的数目,从1到N,D是两台计算机可以直接通信的最大距离。在接下来的N行中,每一行都包含两个整数xi(0<=xi,yi<=10000),这是N台计算机的坐标。从(N+1)-第四行到输入的末尾,有一个接一个地执行的操作。每一行包含以下两种格式之一的操作:
1.“Op”(1<=p<=N),意思是修理计算机p。
2.“Sp q”(1<=p,q<=N),这意味着测试计算机p和q是否能通信。
输入不超过300000行。
Output
对于每个测试操作,如果两台计算机可以通信,则打印“成功”;如果不能,则打印“失败”。
Sample Input
4 1
0 1
0 2
0 3
0 4
O 1
O 2
O 4
S 1 4
O 3
S 1 4
Sample Output
FAIL
SUCCESS
此题使用一个结构体的并查集,根据字符的输入O或者S对结构体进行操作,如果是O且符合题意的距离就合并,如果是S就判断是否为一个根,输出结果
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <string>
#include <stack>
#include <queue>
#include <map>
using namespace std;
const int inf=0x3f3f3f3f;
const int MAX=1e3+5;
int father[MAX];
int sc[MAX];
int find(int a)
{
int x=a;
while(a!=father[a])
{
a=father[a];
}
while(x!=father[x])
{
int z=x;
x=father[x];
father[z]=a;
}
return a;
}
int Union(int a,int b)
{
int x,y;
x=find(a);
y=find(b);
if(x!=y)
{
father[x]=y;
}
return 0;
}
struct Node
{
int x,y;
}curry[MAX];
int dis(Node x,Node y)
{
return (x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y);
}
int main()
{
int n,d;
for(int i=0;i<MAX;i++)
father[i]=i;
scanf("%d%d",&n,&d);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&curry[i].x,&curry[i].y);
}
char temp;
int num=0,x,y;
while(~(scanf("%c",&temp)))
{
if(temp=='O')
{
cin >> x;
sc[num++]=x;
for(int i=0;i<num-1;i++)
if(dis(curry[sc[i]],curry[x])<=d*d)
{
Union(x,sc[i]);
}
}
if(temp=='S')
{
cin >> x >> y;
if(find(x)==find(y)) cout << "SUCCESS" << endl;
else cout << "FAIL" << endl;
}
}
return 0;
}