POJ 2236 - Wireless Network ( 并查集 )

题意

一个计算机网络里的计算机都坏了, 现在有两种操作, “O p”代表修复了p机器, “S p q”代表检查 p, q 两台机器是否连接( 直线距离<=d或者中间有距离<=d的用来联通的机器 )

思路

比赛的时候愣是没读清楚题目意思, 还以为是什么搜索, 瞎瘠薄做了个MLE
没料到居然是个并查集, 注意应该是直线距离 <= d, 不是上下左右走的
每次修复一个机器的时候检查他与其他机器的直线距离, 并将其并入集合中
查找的时候寻找根节点就ojbk

读题没读明白是一方面, 总的来说还是做题经验不够

AC代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>

using namespace std;
const int maxn = 1e3 + 5;
int mrk[maxn];
int n, d;
char op[2];
struct computer{
    int f;
    int x, y;
}p[maxn];

void init(){
    for( int i = 1; i <= maxn; i++ )
        p[i].f = i;
    return;
}

int _find( int a ){
    if( a != p[a].f )
        return _find(p[a].f);
    return a;
}

double getdis( int x1, int y1, int x2, int y2 ){
    double dx = fabs((double)(x1-x2));
    double dy = fabs((double)(y1-y2));
    double dis = sqrt(dx*dx+dy*dy);
    return dis;
}

void _union( const computer a, const computer b ){
    int aa = _find(a.f);
    int bb = _find(b.f);
    if( aa != bb )
        if( getdis(a.x, a.y, b.x, b.y) <= d )
            p[bb].f = aa;
    return;
}

int main()
{
    int a, b;
    init();
    scanf("%d%d",&n, &d);
    for( int i = 1; i <= n; i++ ){
        scanf("%d%d", &p[i].x, &p[i].y);
    }
    while( ~scanf("%s",op) ){
        if( op[0] == 'O' ){
            scanf("%d",&a);
            mrk[a] = 1;
            for(int i = 1; i <= n; i++)
                if( mrk[i] && i != a)
                    _union(p[i], p[a]);
        }
        else if( op[0] == 'S' ){
            scanf("%d%d",&a, &b);
            if( _find(a) == _find(b) )  puts("SUCCESS");
            else  puts("FAIL");
        }
    }
    return 0;
}
posted @ 2018-04-13 11:04  JinxiSui  阅读(160)  评论(0编辑  收藏  举报