Wireless Network POJ - 2236(并查集(维修更新合并))

POJ—2236

在这里插入图片描述
在这里插入图片描述
题意:
有 n 台损坏的电脑,要将他们逐台恢复。若两台电脑能相互通信,有两种情况,一是他们间的距离小于 d,二是他们都能到达第三台已修复的电脑,现在给出全部的电脑位置,对所有电脑进行上述的操作,O x 代表修复第 x 台,S x y 代表判断 x y 能否通信,若能输出 SUCCESS,否则输出 FALL

思路:简单的并查集

用并查集来保存电脑之间的连通情况,每次修好电脑后,就将已经修好的、在他距离范围内的电脑将他连通

#include <iostream>
#include <algorithm>
#include <cmath>
#include <ctype.h>
#include <cstring>
#include <cstdio>
#include <sstream>
#include <cstdlib>
#include <iomanip>
#include <string>
#include <queue>
#include <map>
#define M 50005
#define ll long long
using namespace std;
const int maxn = 1e6+10;
const int INF=0xfffffff;
const int maxx=2005;

using namespace std;

int f[maxn],n,p[maxn][2];
bool m[maxn],dis[1005][1005];

long long fun(int x1,int y1,int x2,int y2)
{
    return ((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

//这里初始化,非常重要,数组里存的是自己数组下标的编号就好了
void init()
{
    int i;
    for(i=0;i<=n;i++)
        f[i]=i;
    return ;
}
//这是找爹的递归函数,不停的去找爹,直到找到祖宗为止,其实就是去找犯罪团伙的最高领导人,擒贼先擒王原则
int getf(int v)
{
    int t=v;
    while(f[t]!=t)
        t=f[t];
    while(v!=t)
    {
        int temp=f[v];
        f[v]=t;
        v=temp;
    }
    return t;
}
//这里是合并两个子集的函数
void Merge(int v,int u)
{
    int t1,t2;//t1,t2分别为v和u的大boss,每次双方的会谈都必须是各自最高领导人
    t1=getf(v);
    t2=getf(u);
    if(t1!=t2)//判断两个结点是否在同一个集合中,即是否为同一个祖先
        f[t2]=t1;
    //靠左原则,左边变成右边的boss
    return;
}
int main()
{
    int d,x,y;
    char s;
    memset(m,false,sizeof(m));
    memset(dis,false,sizeof(dis));
    scanf("%d%d",&n,&d);
    init();
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&p[i][0],&p[i][1]);
    }
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j++)
            if(fun(p[i][0],p[i][1],p[j][0],p[j][1])<=d*d)
                dis[i][j]=dis[j][i]=true;
    while(cin>>s)
    {
        if(s=='O')
        {
            scanf("%d",&x);
            m[x]=true;
            for(int i=1;i<=n;i++)
            {
                if(i!=x&&m[i]&&dis[i][x])
                    Merge(i,x);
            }
        }
        if(s=='S')
        {
            scanf("%d%d",&x,&y);
            if(getf(x)==getf(y))
                printf("SUCCESS\n");
            else
                printf("FAIL\n");
        }
    }

}


/*
                   _ooOoo_
                  o8888888o
                  88" . "88
                  (| -_- |)
                  O\  =  /O
               ____/`---'\____
             .'  \\|     |//  `.
            /  \\|||  :  |||//  \
           /  _||||| -:- |||||-  \
           |   | \\\  -  /// |   |
           | \_|  ''\---/''  |   |
           \  .-\__  `-`  ___/-. /
         ___`. .'  /--.--\  `. . __
      ."" '<  `.___\_<|>_/___.'  >'"".
     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
     \  \ `-.   \_ __\ /__ _/   .-` /  /
======`-.____`-.___\_____/___.-`____.-'======
                   `=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         The program have no BUG.
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值