并查集-Wireless Network POJ - 2236

并查集-Wireless Network POJ - 2236

题目:
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,两电脑之间的通信距离d
输入N个电脑的坐标Xi、Yi
输入两种操作 ‘O’ 和 ‘S’
O表示修复操作,O p表示修复电脑p,即p可与距离d范围内的电脑进行通信(边)
S表示检测,S p q表示检测电脑p与电脑q之间能否正常通信,若能则输出”SUCCESS",否则输出“FAIL”。

思路:

采用并查集------《并查集详解》
电脑未维修时看作是一个个不连通的点,维修后将给定范围d内的电脑标记到同一集合中去,查询的时候只需要查找两个点的祖先是否相同,若相同,说明是同一集合中的点,可正常通信;反之,不可正常通信。

代码:

#include 
#include
#include
#define ll long long
using namespace std;
const int maxn=1e3+5;
int N,d,p,pre[maxn],x[maxn],y[maxn];
bool co[maxn][maxn],vis[maxn];//co来判断联通性,vis判断点是否已加入集合

int Find(int root)//迭代也可,没路径压缩,数据有点问题
{
    while(root!=pre[root])
        root=pre[root];
    return root;
}

int Find1(int root)
{
    if(root==pre[root]) return root;
    return pre[root]=Find(pre[root]);//路径压缩,理论上大部分情况这个应该更快才对
}

int main()
{
    cin>>N>>d;
    memset(co,false,sizeof(co));
    for(int i=1;i<=N;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        pre[i]=i;//每个点的初始祖先是其本身,若不初始化,默认为零就会出错
    }

    for(int i=1;i<=N;i++)
        for(int j=i+1;j<=N;j++)
            if((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])<=d*d)//d的平方
                co[i][j]=co[j][i]=true;

    char op;
    while(~scanf("%c",&op))
    {
        if(op=='O')
        {
            //cout<<"REPAIR:"<
            scanf("%d",&p);//p前面没打&!!!
            vis[p]=true;
            for(int i=1;i<=N;i++)
            {
                if(p!=i&&co[p][i]&&vis[i])//不是同一点,并且是联通的,并且点i已在某集合
                {
                    int u=Find(p),v=Find(i);
                    if(u==v) continue;//p和i的祖先相同
                    pre[u]=v;//p和i的祖先不同,那么把p的祖先加在i的祖先下(结盟)
                }
            }
        }

        else if(op=='S')
        {
            int u,v;
            scanf("%d%d",&u,&v);
            u=Find(u),v=Find(v);
            if(u==v) cout<<"SUCCESS\n";
            else cout<<"FAIL\n";
        }
    }

    return 0;
}

总结:(第一发写的while(scanf()) T了,改成while(cin>>)却过了 )

while(~scanf())与while(scanf())的区别:
并查集-Wireless Network POJ - 2236_第1张图片
while(cin>>):

并查集-Wireless Network POJ - 2236_第2张图片
所以用while(~scanf())和while(cin>>)读入数据是可以的。

你可能感兴趣的:(并查集)