POJ2236——Wireless Network 并查集应用

本文探讨了一种使用并查集解决网络修复过程中电脑连接问题的方法,详细介绍了如何通过并查集判断电脑间的直接连接及间接连接,以及在修复过程中进行电脑修复和连接测试的操作流程。

题目如下:

Wireless Network
Time Limit: 10000MS Memory Limit: 65536K
Total Submissions: 21254 Accepted: 8937

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: 
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个电脑,给你每个电脑的坐标。本来他们都是坏的,要一个个修好。现在可执行两种操作,修好某台电脑,或者查询某两台电脑是否相连。比如两台电脑A和B,如果A,B直接相连,或者存在C同时与A,B相连,都相当于A,B相连。(有点绕233,其实很简单,和互联网一样嘛)

所以你要明白一件事,一台电脑X,只要和某棵树上任何一个节点,也就是一台电脑Y的距离小于d,就可以加入这棵树。因为X总能通过Y与数上的其他电脑相连。

这样的话,再明白不过了,就是并查集嘛。       


代码如下

#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
#include <queue>
#include <ctype.h>
#include <vector>
using namespace std;
#define INF 1000000000
typedef long long LL;
#define MAXN 1010


int par[MAXN];//父亲
int r[MAXN];//树的高度
//初始化n个元素
void init(int n)
{
    for(int i=0;i<n;i++)
    {
        par[i]=i;
        r[i]=0;
    }
}
//查询数的根
int find(int x)
{
    if(par[x]==x)
        return x;
    else
        return par[x]=find(par[x]);
}
//合并x和y所属的集合
void unite(int x,int y){
    x=find(x);
    y=find(y);
    if(x==y)
        return;
    if(r[x]<r[y])
        par[x]=y;
    else
        par[y]=x;
    if(r[x]==r[y])
        r[x]++;
}
//判断x和y是否在同一个树上
bool same(int x,int y)
{
    return find(x)==find(y);
}


struct node{
    int x,y;
};
node a[MAXN];//用于保存每台电脑坐标
int d;
bool judge(node m,node n)//判断是否相连
{
    return (m.x-n.x)*(m.x-n.x)+(m.y-n.y)*(m.y-n.y)<=d*d;
}
int able[MAXN][MAXN]={0};//预处理每两个电脑之间的距离,减少计算次数
int main()
{
    int n;
    scanf("%d%d",&n,&d);
    init(n);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&a[i].x,&a[i].y);
    }
    for(int i=0;i<n-1;i++)
    {
        for(int j=i+1;j<n;j++)
        {
            if(judge(a[i], a[j]))
                able[i][j]=able[j][i]=1;
        }
    }
    getchar();
    char op;
    int x,y;
    vector <int> s;//用一个容器保存已经修好的电脑编号
    while(scanf("%c",&op)!=EOF)
    {
        if(op=='O')
        {
            scanf("%d",&x);
            for(int i=0;i<s.size();i++)
            {
                if(able[s[i]][x-1])
                {
                    unite(x-1,s[i]);
                }
            }
            s.push_back(x-1);
        }
        if(op=='S')
        {
            scanf("%d%d",&x,&y);
            if(same(x-1,y-1))
            {
                printf("SUCCESS\n");
            }
            else
            {
                printf("FAIL\n");
            }
        }
        getchar();
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值