POJ 2236(并查集)

来源:互联网 发布:linux查找rpm包位置 编辑:程序博客网 时间:2024/06/10 20:11

Wireless Network
Time Limit: 10000MS Memory Limit: 65536KTotal Submissions: 26276 Accepted: 10939

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 10 10 20 30 4O 1O 2O 4S 1 4O 3S 1 4

Sample Output

FAILSUCCESS

并查集:

并查集是一种用于处理一些不相交集合的合并和查询问题的数据结构。并查集的实现方法可以有很多种,只要符合其思想即可。这里介绍一种比较简单的实现方法需要一个集合(数组),三个函数(初始化,查询,合并)。

查询函数实现思想:

我们用pre[]数组来表示x元素与pre[x]元素直接相关,之后每个不相交的集合都选出一个代表元素k,对于任意两个元素a,b我们只需要看看他们的代表元素是否相等,具体实现就是通过访问pre[x]是否和x相等,不相等就把x更新为pre[x]重复操作,直到找到pre[x]=x,这就是那个代表元素了,这就是查询函数的功能。

合并函数实现思想:

在实际中我们经常需要将两个元素a,b从不相关转化为相关,这样会对一些其他与a,b相关的元素造成影响,通俗的讲究类似于部队会师总得选出一个总的负责人,具体的做法就是我们找到a,b这两个元素的代表元素,如果是一个那自然不必理会了,如果不相等那就需要其中其中一个代表元素m,将pre[m]修改为另一个元素的代表元素,这就是合并函数需要实现的功能。

初始化函数实现:

根据功能需求自然不难想到初始化每个元素x的pre[x]就是他自己。

小结:

这个实现个人觉得比较好的地方就是每个人元素只记录一个自己的相关元素,这样的操作主要耗时在查询上,还有一种做法是多开数组保存记录,这样的话时间主要消耗在更新记录数组上,而且更新记录数组的操作较为繁琐时间复杂度并不比这种方法低。

具体实现见代码。

题意:

告知有n个已损坏的计算机,在输入中可以执行修复第i台计算机或者询问第i,j台计算机是否可以通信。计算机的通信距离不能超过d,支持间接通信。输出询问的结果。

题解:

每次往图里加一个结点,然后所有与该结点相距<=d的结点都和该结点连上线,然后询问i,j结点是否在图中可达。典型的并查集应用题。

代码:

#include<iostream>#include<cstring>#include<math.h>#include<stdlib.h>#include<cstring>#include<cstdio>#include<utility>#include<algorithm>using namespace std;typedef long long ll;const int Max = 1005;const int mod = 1e9+7;pair<int ,int> arr[Max];int t[Max];//并查集int pre[Max];int Find(int x)//查询{    while(pre[x] != x)        x = pre[x];    return x;}void Union(int a, int b)//合并{    pre[Find(b)] = Find(a);}void init( )//初始化{    for(int i=0; i<Max; i++)        pre[i] = i;}int N, d;bool connect(int a, int b){    int dx = arr[a].first - arr[b].first;    int dy = arr[a].second - arr[b].second;    int length = dx*dx + dy*dy;    return length <= d;}int main( ){    //freopen("input.txt","r",stdin);    cin>>N>>d;    d *= d;    for(int i=1; i<=N; i++)        scanf("%d %d", &arr[i].first,&arr[i].second);    getchar();    init();    char ch;    int cnt = 0;    while((ch=getchar())!= EOF)    {        if(ch == 'O')        {            int a;            cin>>a;            t[cnt++] = a;            for(int i=0; i<cnt-1; i++)                if(connect(t[i], a))                    Union(t[i], a);        }        else if(ch == 'S')        {            int a,b;            cin>>a>>b;            if(Find(a) == Find(b))                cout<<"SUCCESS"<<endl;            else                cout<<"FAIL"<<endl;        }        getchar();    }    return 0;}


0 0