【并查集】poj 2236 Wireless Network

题目描述:

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

 

中文大意:

东南亚发生地震,工作人员进行网络修复。

由于硬件限制,每台计算机只能与 (0,d] 范围内的计算机进行通信,但却可以充当中介,即如果计算机 C 可以与计算机 A 和计算机 B 进行通信,则计算机 A 和计算机 B 可以进行通信。

在修复网络的过程中,工作人员可以随时执行两种操作:修复一台计算机、测试两台计算机是否可以通信。

我们的工作是回答所有测试操作。

 

思路:

一个计算机网络就是一个集合。

每修复一台计算机,便尝试将它与 (0,d] 范围内的所有已经被修复的计算机进行连接。

两台计算机可以通讯的前提条件是:在同一个集合中,且均已被修复。

 

代码:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<math.h>
using namespace std;

//记录各节点的位置信息 
struct node{
    int x,y;
}pos[1002];

int sets[1002];//各节点的所属集 
int height[1002];//各集合的树高 
bool repaired[1002] = {false};//是否被修理

int n,d;

//初始化,各节点属于独立的集合 
void init(){
    for(int i=1;i<=n;i++){
        sets[i] = i;
        height[i] = 1;
    }
}

//查询节点 x 的所属集 
int find(int x){
    //寻找根节点 
    int root = x;
    while(root != sets[root]){
        root = sets[root];
    } 
    
    //路径压缩:将路径上节点的所属集修改为根节点 
    int i = x;
    while(sets[i] != root){
        int j = sets[i];
        sets[i] = root;
        i = j;
    }
    return root;
}

//合并 
void union_set(int x, int y){
    //寻找节点 x 的所属集 
    x = find(x);
    //寻找节点 y 的所属集 
    y = find(y);
    
    //若两个节点的所属集树高相同,则将 x 的所属集并到 y 的所属集 
    if(height[x] == height[y]){
        sets[x] = y;
        height[y]++;
    }//否则,将矮树并到高树,高树的树高保持不变 
    else if(height[x] > height[y]){
        sets[y] = x;
    }
    else{
        sets[x] = y;
    }
}

//计算两个节点之间的距离 
int cal_dis(int x, int y){
    int dis_x = pos[x].x - pos[y].x;
    int dis_y = pos[x].y - pos[y].y;
    return dis_x*dis_x + dis_y*dis_y;
}

int main(){
    scanf("%d %d", &n, &d);
    init();
    
    for(int i=1;i<=n;i++){
        scanf("%d %d", &pos[i].x, &pos[i].y);
    }
    
    char c;
    int x,y;
    getchar();//scanf("%c", &c) 会读入回车 
    while(~scanf("%c", &c)){
        if(c == 'O'){
            scanf("%d", &x);
            repaired[x] = true;
            
            //将节点 x 合并到 (0,d] 范围内的集合中 
            for(int i=1;i<=n;i++){
                if(i == x || !repaired[i]){
                    continue;
                }
                
                int dis = cal_dis(x, i);
                if(dis <= d*d){
                    union_set(x, i);
                }
            }
        }
        else if(c == 'S'){
            scanf("%d %d", &x, &y);
            
            //两台计算机均被修理,且在同一个通讯网络中 
            if(repaired[x] && repaired[y] && find(x) == find(y)){
                printf("SUCCESS
");
            }
            else{
                printf("FAIL
");
            }
        }
        getchar();
    }
} 
作者:老干妈就泡面
本文版权归作者和博客园共有,欢迎转载,但请给出原文链接,并保留此段声明,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/bjxqmy/p/14482543.html