1. 程式人生 > >並查集——poj2236(帶權並查集)

並查集——poj2236(帶權並查集)

algorithm blog oid poj2236 stream 命令 net 最大 spa

題目:Wireless Network

題意:給定n臺已損壞計算機的位置和計算機最遠通信距離d,然後分別根據命令執行以下兩種操作:

  1. "O p" (1 <= p <= N) :表示修理計算機p;
  2. "S p q" (1 <= p, q <= N) :表示檢測計算機p和計算機q能否通信。

輸出:能通信則輸出"SUCCESS",否則輸出"FAIL"

題解:

帶權並查集還是那個重要的知識點——關系。

此題,我們使用一個repair數組存儲每臺電腦的狀態(損壞還是好的)

然後就是對每次修好的電腦對其它已經修好的電腦遍歷,如果距離小於等於最大通信距離就將他們合並。之後判斷2臺電腦是不是一個集合中就行了。

代碼:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

int n,k;
bool repair[1005];		//為真則修好了 

struct point{
	int pre;
	int x,y;
}c[1005];

void init()
{ 
	for(int i=1;i<=n;i++){
		c[i].pre = i;
		repair[i] = false;
	}
}

int find(int x)
{
	if(x==c[x].pre)	return x;
	c[x].pre = find(c[x].pre);
	return c[x].pre;
}

void unite(const point p1, const point p2)  
{  
    int root1, root2;  
    root1 = find(p1.pre);  
    root2 = find(p2.pre);  
    if(root1 != root2)  
        if((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) <= k * k)  
            c[root2].pre = root1;  
}  

int main()
{
	cin>>n>>k;
	init();
	for(int i=1;i<=n;i++){
		scanf("%d%d",&c[i].x,&c[i].y);
	}
	char s[5];
	int a,b;
	while(scanf("%s",s)!=EOF){
		if(s[0]==‘O‘){
			scanf("%d",&a);
			repair[a] = true;
			for(int i=1;i<=n;i++){
				if(i!=a && repair[i]){
					unite(c[a],c[i]);
				}
			}
		}
		else{
			scanf("%d%d",&a,&b);
			if(find(a) == find(b)){
				printf("SUCCESS\n");
			}
			else	printf("FAIL\n");
		}
	}
	return 0;
} 

並查集——poj2236(帶權並查集)