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.
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.
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
一点理解
因为题目中说只要两台电脑间有一台电脑能够和二者进行通信,那么它们就可以进行通信。可以利用并查集来存储能够进行通信的电脑,能够通信的电脑们作为一个集合。
判断两台电脑能否进行通信,只需要判断它们是否在同一个集合即可。
除了基本的并查集函数,还要有判断两台电脑间的距离是否小于等于d的函数
对于每一次修复操作以后,标记已经修复过的电脑,并遍历一遍除刚刚修复的电脑外的所有电脑,看两台电脑之间能否进行通信。如果能够进行通信,就进行合并操作。
注意需要用到的数组的创建和数组的初始化。
我的代码
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<math.h>
using namespace std;
const int N=1e5;
typedef pair<int,int>P;
P dis[N+5];
int bcj[N+5];
bool used[N+5];
int n,d;
int Find(int x)
{
if(bcj[x] < 0) return x;
return bcj[x] = Find(bcj[x]);
}
void Union(int x, int y)
{
x = Find(x), y = Find(y);
if(x == y) return;
bcj[x] += bcj[y];
bcj[y] = x;
}
bool pan(P a,P b)
{
int dx=a.first-b.first;
int dy=a.second-b.second;
return sqrt(double(dx*dx)+double(dy*dy))<=d;
}
int main()
{
scanf("%d%d",&n,&d);
memset(used,0,sizeof used);
memset(bcj,-1,sizeof bcj);
for(int i=1;i<=n;i++)
scanf("%d%d",&(dis[i].first),&(dis[i].second));
char op;
int x,y;
while(scanf("%c",&op)!=EOF)
{
if(op=='O')
{
scanf("%d",&x);
used[x]=1;
for(int i=1;i<=n;i++)//遍历所有结点看是否能与x连接
{
if(used[i]&&i!=x&&pan(dis[x],dis[i]))
Union(i,x);
}
}
else if(op=='S')
{
scanf("%d%d",&x,&y);
if(Find(x)==Find(y))
printf("SUCCESS\n");
else
printf("FAIL\n");
}
}
return 0;
}
学姐的代码
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
using namespace std;
const int N = 1e5;
typedef pair<int, int> P;
P dis[N + 5];
int bcj[N + 5];
bool used[N + 5];
int n, d;
int Find(int x)
{
if(bcj[x] < 0) return x;
return bcj[x] = Find(bcj[x]);
}
void Union(int x, int y)
{
x = Find(x), y = Find(y);
if(x == y) return;
bcj[x] += bcj[y];
bcj[y] = x;
}
inline bool dist(P a, P b)
{
int x = a.first - b.first, y = a.second - b.second;
return sqrt(double(x * x) + double(y * y)) <= d;
}
int main()
{
int x, y;
char op;
while(cin >> n >> d) {
memset(bcj, -1, sizeof bcj);
memset(used, false, sizeof used);
for(int i = 1; i <= n; ++i) {
cin >> dis[i].first >> dis[i].second;
}
while(cin >> op) {
if(op == 'O') {
cin >> x;
used[x] = true;
for(int i = 1; i <= n; ++i) {
if(used[i] && i != x && dist(dis[i], dis[x])) Union(i, x);
}
}
if(op == 'S') {
cin >> x >> y;
if(Find(x) == Find(y)) puts("SUCCESS");
else puts("FAIL");
}
}
}
return 0;
}