POJ 2236 Wireless Network 并查集基础

题目描述
一场地震在东南亚发生了。不幸的是ACM组织通过电脑建立的无线网络遭到了毁灭性的影响—--网络中所有的电脑都损坏了。在陆续的维修电脑之后,无线网络有逐渐开始再一次运作了。由于硬件的制约,每两台电脑只能保持不超过d米的距离,才可以直接进行通讯。但是每台电脑又可以作为其它两台电脑通讯的中介点,也就是说假设A电脑与B电脑不在能直接通讯的的范围内,但是它们可以通过同时能与A和B电脑通讯的C电脑建立间接通讯关系。
在维修的过程中,维修者可以进行两种操作:维修一台电脑或者检测两台电脑之间是否能够通讯。你的任务就是解答每一次的检测操作。
输入
第一行包含两个整数N和d (1 <= N <= 1001, 0 <= d <= 20000).N表示电脑的数量,电脑编号从1开始到N,d为两台能直接通讯的电脑所需保持的距离的最大值。在接下来的N行里,每行包含两个整数xi, yi (0 <= xi, yi <= 10000),表示N台电脑的坐标。接下来的一系列的输入都表示维修者的操作,每种操作都是以下两种中的一种:
1. "O p" (1 <= p <= N),表示维修第p台电脑。
2. "S p q" (1 <= p, q <= N), 表示检测p与q电脑是否能够通讯。
输入不会超过300000 行。 
输出
对于每组检测操作,若两台电脑能进行通讯就输出"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 <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 1005;

int flag[N],imap[N][N];   //flag 判断是否维修  imap判断是否可以直接联通,不借助任何中间点
int parent[N],x[N],y[N];  //存储根节点与位置
int mul(int x)
{
    return x*x;
}
int root(int x)
{
     return   parent[x] == x ?  x : parent[x]=root( parent[x] );
}
void make(int a,int b)//并查集的并操作
{
    int f1=root(a);
    int f2=root(b);
    if(f1!=f2)
        parent[f2]=f1;
}
void check(int a,int b)
{
    if(root(a)==root(b))
        printf("SUCCESS\n");
    else
        printf("FAIL\n");
}
int main()
{
    int n,m;
    double d;
    scanf("%d%lf",&n,&d);
    memset(flag,0,sizeof(flag));
    memset(imap,0,sizeof(imap));
    for(int i=1;i<=n;i++){
      scanf("%d%d",&x[i],&y[i]);
      parent[i]=i;
    }

    for(int i=1;i<=n;i++)
      for(int j=i+1;j<=n;j++)
         if(sqrt(mul(x[i]-x[j])+mul(y[i]-y[j]))<=d){
            imap[i][j]=1;
            imap[j][i]=1;  //从i到j或者从j到i可以直接联通
         }
     char s[10];
     while(scanf("%s",s)!=EOF)
     {    int a,b;
         if(strcmp(s,"O")==0)
         {
             scanf("%d",&a);
             flag[a]=1; //位置为ipos的节点进行了维修
             for(int i=1;i<=n;i++)
                if(imap[i][a]&&flag[i])  //将所有已经维修好的站点与a进行比较判断是否可以联通
                    make(a,i);
         }
         else
         {

             scanf("%d%d",&a,&b);
             check(a,b);

         }
     }
     return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值