POJ - 2236 Wireless Network(并查集)

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:
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台电脑一开始全是坏掉的,用O 操作修复第i台电脑,用S操作检查x和y号电脑是否互联,其中两台好的电脑如果距离小于D则可以互联,每台电脑的标号是他输入时的下标,现在输入所有电脑的坐标,查询两两电脑之间是否可以直接或间接互联

一开始看到坐标以为是图论,后来发现因为电脑之间可以间接联通,因此能够在一定距离内修好并连同的电脑可以作为一个桥梁使附近剩下的电脑尽肯能的联通,因此是类似于并查集中收揽集合的过程,而检查是否互联也可以用并查集中find函数实现。

首先输入所有电脑的坐标,并计算两两之间的建立,如果两两距离小于D还能继续将其列入可能互联的待选列表中(vector)

然后修电脑的操作将电脑修好的标记标为true,并通过之前的待选列表将刚修好的电脑尽可能的利用并查集的join函数与其他电脑互联。

查询时只需check两两电脑是否在同一个集合中即可判断是否互联

#include<stdio.h>///并查集
#include<set>
#include<math.h>
#include<string>
#include<string.h>
#include<iostream>
#include<queue>
#include<vector>
#define LL long long
using namespace std;
struct com
{
    double x,y;
} a[1004];
int n,t,ans,d,tmp;
double dis[1005][1008];
vector<int>v[1005];
bool vis[1005];
int x,y;
int zz[1005];
int finds(int x)
{
    int r=x,t;
    while(r!=zz[r])
    {
        t=r;
        r=zz[r];
        zz[t]=zz[r];
    }
    return r;
}
void join(int a,int b)
{
    int fa=finds(a),fb=finds(b);
    if(fa!=fb)
    {
        zz[fa]=fb;
    }
}
int main()
{
    while(scanf("%d%d",&n,&d)!=EOF)
    {
        memset(vis,false,sizeof(vis));
        memset(dis,0x3f,sizeof(dis));
        for(int i=1;i<=n;i++)v[i].clear();
        for(int i=1;i<=n;i++)zz[i]=i;
        for(int i=1; i<=n; i++)
        {
            scanf("%lf%lf",&a[i].x,&a[i].y);
            for(int j=1; j<i; j++)
            {
                dis[i][j]=dis[j][i]=sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y));
                if(dis[i][j]<=d)///将每个电脑周围的可选距离的电脑收入vector中待选
                {
                    v[i].push_back(j);
                    v[j].push_back(i);
                }
            }
        }
        char flag[3];
        while(scanf("%s",flag)!=EOF)
        {
            if(flag[0]=='O')
            {
                scanf("%d",&tmp);
                vis[tmp]=true;
                for(int i=0; i<v[tmp].size(); i++)
                {
                    if(vis[v[tmp][i]])
                    {
//                        printf("%d-------%d\n",vis[v[tmp][i]],v[tmp][i]);
                        join(v[tmp][i],tmp);
                    }
                }
//                for(int i=1;i<=n;i++)
//                {
//                    printf("%d====>%d\n",i,zz[i]);
//                }
            }
            else
            {
                scanf("%d%d",&x,&y);
                if(finds(x)==finds(y))
                {
                    printf("SUCCESS\n");
                }
                else
                {
                    printf("FAIL\n");
                }
            }
        }
    }
    return 0;
}

posted @ 2018-03-21 00:34  KuroNekonano  阅读(86)  评论(0编辑  收藏  举报