这是一篇题解。
题面
原题面
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.
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:
- "O p" (1 <= p <= N), which means repairing computer p.
- "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.
翻译
东南亚发生地震。亚洲合作医疗队(ACM)已与膝上计算机建立了无线网络,但由于意外的余震袭击,网络中的所有计算机都被破坏了。电脑被一一修复,网络逐渐恢复工作。由于硬件限制,每台计算机只能直接与不超过d米的计算机通信。但是,每台计算机都可以视为其他两台计算机之间通信的中介,也就是说,如果计算机A和计算机B可以直接通信,或者有计算机C可以同时与A和B通信,则计算机A和计算机B可以通信。
在修复网络的过程中,工作人员可以随时执行两种操作:修复计算机,或测试两台计算机是否可以通信。您的工作是回答所有测试操作。
输入值
第一行包含两个整数N和d(1 <= N <= 1001,0 <= d <= 20000)。 N是计算机的数量,从1到N,而D是两台计算机可以直接通信的最大距离。在接下来的N行中,每行包含两个整数xi,yi(0 <= xi,yi <= 10000),这是N个计算机的坐标。从第(N + 1)行到输入的末尾,有一些操作,这些操作是一个接一个地执行的。每行包含以下两种格式之一的操作:
1.“ O p”(1 <= p <= N),表示维修计算机p。
2.“ S p q”(1 <= p,q <= N),表示测试计算机p和q是否可以通信。
输入不会超过300000行。
对于每项测试操作,如果两台计算机可以通信,则打印“ SUCCESS”,否则,则打印“ FAIL”。
题目解析
并查集做法
我们只需要这么做,
1、输入,并做好预处理(将点 i 与 1~i-1 的距离的平方算出)
2、输入测试数据.
若是修理命令则将第 p 号电脑的 vis[p] 值赋为 true ,并将点 p 与所有没有建立连接并且距离不超过 d 并且被修理的电脑用并查集合并起来(因为之前我们存的是距离的平方所以代码中应该是“d * d”)
若是测试命令则进行判断,如果 vis[a] 与 vis[b] 都为 1 并且 find(a) = find(b) 则 print SUCCESS,否则 print FAIL。
本题重点考察并查集的运用,此题不能按照模板打。
#include <cstdio>
using namespace std;
int n, d;
int p, q;
struct computer{
int x, y;
}com[1050];
int par[1050];
int vis[1050];
int map[1050][1050];
int find(int s)
{
if(par[s] == s)
return s;
int k = s;
while(k != par[k])
k = par[k];
par[s] = k;//优化
return k;
}
int main()
{
scanf("%d%d",&n,&d);
for(int i = 1; i <= n; i++)
{
par[i] = i;
scanf("%d%d", &com[i].x, &com[i].y);
map[i][i] = 0;
for(int j = i - 1; j >= 1; j--)
map[i][j] = map[j][i] = (com[i].x - com[j].x) * (com[i].x - com[j].x) + (com[i].y - com[j].y) * (com[i].y - com[j].y);
}
char cmd;
while(scanf("%c", &cmd) != EOF)
{
if(cmd == 'O')
{
scanf("%d", &p);
vis[p] = 1;
for(int i = 1;i <= n; i++)
{
if(map[p][i] <= d * d && i != p && vis[i])
{
int f = find(p);
int g = find(i);
if(f != g);
par[g] = f;
}
}
}
else if (cmd == 'S')
{
scanf("%d%d", &p, &q);
if(vis[p] && vis[q] && find(p) == find(q))
printf("SUCCESS
");
else
printf("FAIL
");
}
}
}
顺带点赞收藏关注一下叭。