POJ 2236 Wireless Network(并查集)


http://poj.org/problem?id=2236


题意:给出一些电脑,它们目前都是损坏的状态,然后会依次修其中的一些,如果两台电脑都被修好了,并且它们之间的距离小于等于d,那么这两台电脑是可以沟通的。如果AB可以沟通,BC可以沟通,那么AC也是可以沟通的。现在查询两台电脑的时候,问它们是不是可以沟通的。


刚开始的时候,每一台电脑都是一个集合。每一个集合之内的电脑都可以互相沟通,不同集合内的电脑目前不可以沟通。某一台电脑A刚被修好的时候,要把其他已经维修好的电脑都枚举一遍,如果B距离符合要求,那么就说明这两台电脑之间可以沟通,那么A和B所在的集合中所有的电脑都可以沟通,A所在的集合和B所在的集合可以合并。处理好了以后,那么当前状态下,还是满足每一个集合内的电脑都可以互相沟通,不同集合内的电脑目前不可以沟通(比如两个不同集合中有CD,A在修好之前两者不能沟通,现在想要沟通一定也只能靠A作为桥梁,A连上C所在集合中任何一台电脑并且连上D所在集合中的任何一台电脑就可以,但是刚才A已经和每一台电脑都试过了,如果可以连上一定是会合并集合的,不会出现现在不同集合的情况。有点类似归纳法,到最后一步,还是满足的。


不要忘了初始化。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<string>
#define MAXN 1005
using namespace std;
int n, d, p, q, m;
char s[20];
int Par[MAXN], Rank[MAXN], re[MAXN], X[MAXN], Y[MAXN];
bool OK(int u, int v)
{
    if ((X[u] - X[v]) * (X[u] - X[v]) + (Y[u] - Y[v]) * (Y[u] - Y[v]) <= d * d) return true;
    else return false;
}
void init(int n)
{
    for (int i = 0; i < n; i++)
    {
        Par[i] = i;
        Rank[i] = 0;
    }
}
int Find(int x)
{
    if (Par[x] == x)
    {
        return x;
    }
    else
    {
        return Par[x] = Find(Par[x]); //路径压缩
    }
}
void unite(int x, int y)
{
    x = Find(x);
    y = Find(y);
    if (x == y) return;
    if (Rank[x] < Rank[y])
    {
        Par[x] = y;
    }
    else
    {
        Par[y] = x;
        if (Rank[x] == Rank[y]) Rank[x]++;
    }
}
bool same(int x, int y)
{
    return Find(x) == Find(y);
}
int main()
{
    scanf("%d%d", &n, &d);
    for (int i = 0; i < n; i++) scanf("%d%d", &X[i], &Y[i]);
    memset(re, 0, sizeof(re));
    init(n);
    while (~scanf("%s", s))
    {
        if (s[0] == 'O')
        {
            scanf("%d", &m);
            m--;
            for (int i = 0; i < n; i++)
                if (OK(m, i) && re[i] == 1 && m != i)
            {
                unite(m, i);
            }
            re[m] = 1;
        }
        if (s[0] == 'S')
        {
            scanf("%d%d", &p, &q);
            p--;
            q--;
            if (same(p, q)) printf("SUCCESS\n");
            else printf("FAIL\n");
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值