【JZOJ 1152】无线网络(并查集)

问题描述
有一个由n台计算机组成的无线网络。(n <= 1001),正常情况下,每台计算机都能跟与它距离不超过d的任何计算机通讯(d <= 20000)。地震发生了。所有的计算机都陷入瘫痪。专家们试着一台一台地修复计算机,以恢复整个无线网络。有时在修复的过程中,他们需要测试一下某两台计算机能否通讯(如果他们能通过别的正常的计算机进行通讯,也算他们之间可以通讯,即“能否通讯”可以是间接的)。
你的任务,就是模拟修复网络的过程,并回答“能否通讯”的询问。
输入
第一行两个整数,N和d,N表示计算机的数目,d表示两台计算机直接可直接通讯的最大距离。接下来的N行,每行两个整数Xi,Yi,表示每台计算机的坐标。接下来有许多行,每行都是一个操作(或者是修复操作,或者是询问操作)。
操作的格式如下:
O p (1 <= p <= N) 修复操作,表示修复编号为p的电脑;
S p q (1 <= p, q <= N) 询问操作,询问编号为p和编号为q的电脑能否通讯。
如果一台电脑尚未被修复,则它不能和任何电脑通讯。
输出
对于每个询问操作:如果能够通讯,输出一行SUCCESS;如果无法通讯,输出一行FAIL
样例输入
4 1
0 1
0 2
0 3
0 4
O 1
O 2
O 4
S 1 4
O 3
S 1 4
样例输出
FAIL
SUCCESS
算法讨论
对于每个修复操作进行连边,然后跑并查集。

#include <iostream>
#include <cstdio>
#include <math.h>
#include <cmath>
using namespace std;
#define maxn 4006
int point[maxn][3],f[maxn];
bool v[maxn];
double dis[maxn][maxn];
int n,d,p,q;

int sqr(int a)
{
    return a*a;
}

int find(int x)
{
    if (f[x]==x)
        return x;
    f[x]=find(f[x]);
    return f[x];
}

int work(int x,int y)
{
    int fx,fy;
    fx=find(x);
    fy=find(y);
    if (fx!=fy)
        f[fy]=fx;
    return 0;
}

int main()
{
    scanf("%d%d",&n,&d);
    for (int i=1;i<=n;i++)
    {
        scanf("%d%d",&point[i][1],&point[i][2]);
        for (int j=1;j<i;j++)
        {
            dis[i][j]=sqrt(sqr(point[i][1]-point[j][1])+sqr(point[i][2]-point[j][2]));
            dis[j][i]=dis[i][j];
        }
        f[i]=i;
    }
    char c;
    scanf("%c",&c);
    while (~scanf("%c",&c))
    {
        if (c=='O')
        {
            scanf("%d",&p);
            v[p]=1;
            for (int i=1;i<=n;i++)
                if (dis[p][i]<=d && v[i])
                    work(p,i);
        }
        else
        {
            scanf("%d%d",&p,&q);
            if (find(p)==find(q) && v[p] && v[q])
                printf("SUCCESS\n");
            else
                printf("FAIL\n");
        }
        scanf("%c",&c);
    }
}

猜你喜欢

转载自blog.csdn.net/fallen_angel001/article/details/79189593