题目链接:http://poj.org/problem?id=2236
Description
An earthquake takes place in Southeast Asia. The ACM (Asia Cooperated Medical team) have set up a wireless network with the lap computers, but an unexpected aftershock attacked, all computers in the network were all broken. The computers are repaired one by one, and the network gradually began to work again. Because of the hardware restricts, each computer can only directly communicate with the computers that are not farther than d meters from it. But every computer can be regarded as the intermediary of the communication between two other computers, that is to say computer A and computer B can communicate if computer A and computer B can communicate directly or there is a computer C that can communicate with both A and B.
In the process of repairing the network, workers can take two kinds of operations at every moment, repairing a computer, or testing if two computers can communicate. Your job is to answer all the testing operations.
题面翻译:
东南亚发生地震。亚洲合作医疗队(acm)与笔记本电脑建立了无线网络,但意外的余震袭击,网络中的所有电脑都坏了。电脑一台接一台地修好了,网络逐渐恢复了工作。由于硬件的限制,每台计算机只能与距离它不超过d米的计算机直接通信。但是每台计算机都可以看作是其它两台计算机之间通信的中介,也就是说,如果计算机A和计算机B可以直接通信,或者有一台计算机C可以同时与A和B通信,那么计算机A和计算机B就可以通信。
在修复网络的过程中,工人可以在每一时刻进行两种操作,修复一台计算机,或者测试两台计算机是否可以通信。你的工作是回答所有的测试操作。
Input
The first line contains two integers N and d (1 <= N <= 1001, 0 <= d <= 20000). Here N is the number of computers, which are numbered from 1 to N, and D is the maximum distance two computers can communicate directly. In the next N lines, each contains two integers xi, yi (0 <= xi, yi <= 10000), which is the coordinate of N computers. From the (N+1)-th line to the end of input, there are operations, which are carried out one by one. Each line contains an operation in one of following two formats:
1. "O p" (1 <= p <= N), which means repairing computer p.
2. "S p q" (1 <= p, q <= N), which means testing whether computer p and q can communicate.
The input will not exceed 300000 lines.
Output
For each Testing operation, print "SUCCESS" if the two computers can communicate, or "FAIL" if not.
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
有n台计算机,每台计算机都损坏了,只有距离小于等于d的好的计算机可以相连。现在有两种操作,一种是修复计算机,另一种是询问两个计算机是否连通。如果能连通,则输出"SUCCESS",否则输出 "FAIL" 。
用并查集来判断两个计算机是否连通。存一下每个点的坐标,然后每次查询操作只需要判断两个点是不是指向同一个点即可,每次修复操作,都将满足条件的好的计算机连向自己。
分析一下时间复杂度,1000个点,不超过300000的输入,所以最坏也就3e8的时间复杂度,所以可以莽。
#include
#include
#include
#include
using namespace std;
struct node{
int x,y; //点的坐标
int link,fix; //link表示该点连接的点,fix表示该点的computer是否已经修好
}pc[1005];
void init(int n){ //初始化并查集
for(int i = 0; i <= n; i++){
pc[i].link = i;
pc[i].fix = 0;
}
}
double hl(struct node a,struct node b){ //求两个点之间的距离
double x = a.x - b.x;
double y = a.y - b.y;
double ans = sqrt(x*x+y*y);
return ans;
}
int fd(int n){ //查找该点属于哪个集合
if(pc[n].link == n)return n;
else return pc[n].link = fd(pc[n].link);
}
int main(){
int n,d;
scanf("%d%d",&n,&d);
init(n); //初始化
for(int i = 1; i <= n; i++){
scanf("%d%d",&pc[i].x,&pc[i].y); //读入n个computer的位置
}
getchar();
char op;
int s,e;
while(~scanf("%c%d",&op,&s)){ //读入操作直到结束
if(op == 'S'){ //如果是查询操作
scanf("%d",&e); //则需要再读入一个点
int fb,fe;
fb = fd(s); //fb表示s属于的集合
fe = fd(e); //fe表示e属于的集合
if(fb == fe) //如果两个的属于同一个集合,则表示联通
printf("SUCCESS\n");
else
printf("FAIL\n");
}
else{ //修computer的操作
if(pc[s].fix == 0){ //如果这个点没修过,遍历所有点,把所有能连到的点都连上
for(int i = 1; i <= n; i++){
if(pc[i].fix && hl(pc[s],pc[i]) <= d){ //如果这个点被修过,且和当前修好的点距离满足条件,则连到当前修好的点
int fn = fd(i); //找到这个点属于哪个集合
pc[fn].link = s; //直接把这个集合的点指向这个点
}
}
pc[s].fix = 1; //标记一下这个点修过
}
}
getchar();
}
return 0;
}