POJ2236 무선 네트워크

题目链接: POJ2236 무선 네트워크
시간 제한 : 10000MS 메모리 제한 : 65536k 나
총 제출 : 49,928 허용 : 20443

설명
지진은 동남 아시아에서 일어난다. ACM (아시아 제공처 의료 팀) 무릎 컴퓨터와 무선 네트워크를 설정했지만, 예상치 못한 여진은 네트워크의 모든 컴퓨터가 모든 졌 있었다, 공격했다. 컴퓨터는 하나 하나를 수리하고, 네트워크는 점차적으로 다시 작업을 시작했다. 때문에 하드웨어를 제한의 각 컴퓨터는 직접 발 D 미터 이상인 멀리있는 컴퓨터와 통신 할 수있다. 그러나 모든 컴퓨터는 컴퓨터 A와 컴퓨터 B가 직접 통신 할 수 또는 A 모두와 통신 할 수있는 컴퓨터 C가있는 경우 컴퓨터 A와 컴퓨터 B가 통신 할 수 있다고하는 두 컴퓨터 간의 통신을 매개로 간주 될 수있다 비.

네트워크를 수리하는 과정에서 작업자가 컴퓨터 수리, 또는 두 컴퓨터가 통신 할 수 있는지 테스트, 매 순간에 작업 두 종류의 수 있습니다. 당신의 임무는 모든 테스트 작업을 대답하는 것입니다.

입력
첫 줄 두 정수 N과 D 포함 (1 <= N을 <= 1,001, 0 <= D <= 20000). 여기서 N은 1 내지 N 번째하는 컴퓨터의 수이고, D는 두 개의 컴퓨터가 직접 통신 할 수있는 최대 거리이다. 다음 N 라인에서, 각각의 N은 시스템의 좌표 두 정수 XI 이순신 (0 <= XI 이순신 <= 10000) 함유한다. 입력의 종료까지 (N + 1) 번째 행에서 하나씩 수행되는 작업이있다. 각 행은 두 가지 형식을 다음 중 하나의 작업을 포함 :

  1. "O를 P '(1 <= p <= N), 컴퓨터 (P)를 복구 방법.
  2. "S의 PQ"(1 <= P, Q <= N), 컴퓨터 p와 q가 통신 할 수 있는지 여부를 테스트하는 방법.

입력 300000 개 라인을 초과하지 않음.

출력
각 시험 작동을 위해 두 컴퓨터가 통신 할 수있는 경우, "성공"을 인쇄, 또는 "FAIL"아니라면.

샘플 입력

4 1
0 1
0 2
0 3
0 4
O 1
O 2
O 4
S 1~4
O 3
1 4 S

샘플 출력

FAIL
성공

프로그램 설명 :

디스 조인트 세트 싸이클 모든 컴퓨터 컴퓨터를 복구하고, 거리 (d)가 결합하여보다 작은 수정마다.
또한 그 공간과 캐리지 리턴을주의 할 때 입력 (때문에 오랜 시간 동안이 작은 카드 세부 사항 ...)

다음과 같이 코드입니다 :

#include <iostream>
#include <cstdio>
#define MAX 1001
using namespace std;
struct point {
	int x, y;
} p[MAX + 1];
//par数组记录根,rank数组记录树的高度,vis数组标记是否已经修好 
int par[MAX + 1], rank[MAX + 1], vis[MAX + 1];
int n, d, dis;
void init() {
	for(int i = 1; i <= n; i++) {
		par[i] = i;
		rank[i] = 0;
		vis[i] = 0;
	}
}
int find(int x) {
	if(par[x] == x)
		return x;
	else
		return par[x] = find(par[x]);
}
void merge(int x1, int y1) {
	dis = (p[x1].x - p[y1].x) * (p[x1].x - p[y1].x) + (p[x1].y - p[y1].y) * (p[x1].y - p[y1].y);
	x1 = find(x1);
	y1 = find(y1);
	if(x1 == y1)
		return;
	if(rank[x1] < rank[y1] && dis <= d * d)
		par[x1] = y1;
	else if(rank[x1] >= rank[y1] && dis <= d * d){
		par[y1] = x1;
		if(rank[x1] == rank[y1])
			rank[x1]++;
	}
}
bool same(int x, int y) {
	return find(x) == find(y) ? true : false;
}
int main() {
	scanf("%d%d", &n, &d);
	init();
	char ch[2];
	for(int i = 1; i <= n; i++) {
		scanf("%d%d", &p[i].x, &p[i].y);
	}
	while(~scanf("%s", ch)) {
		if(ch[0] == 'O') {
			int k;
			scanf("%d", &k);
			vis[k] = 1;
			for(int i = 1; i <= n; i++) {
				//不在一个集合里并且已经被修好了 
				if(!same(i, k) && i != k && vis[i] == 1) {
					merge(i, k);
				}
			}
		}
		else {
			int p, q;
			scanf("%d%d", &p, &q);
			if(same(p, q))
			//在同一个集合里 
				printf("SUCCESS\n");
			else
				printf("FAIL\n");
		}
	}	
	return 0;
} 

흡수는 scanf 버퍼에 문자 CH 변수를 선언하기 전에, 그러나 인해 제대로 출력 할 수없는 공백 캐리지 리턴 될 것이다. 변경 후 다음 코드, 위의 문제에 대한 효과적인 솔루션입니다.

#include <iostream>
#include <cstdio>
#define MAX 1001
using namespace std;
struct point {
	int x, y;
} p[MAX + 1];
//par数组记录根,rank数组记录树的高度,vis数组标记是否已经修好 
int par[MAX + 1], rank[MAX + 1], vis[MAX + 1];
int n, d, dis;
void init() {
	for(int i = 1; i <= n; i++) {
		par[i] = i;
		rank[i] = 0;
		vis[i] = 0;
	}
}
int find(int x) {
	if(par[x] == x)
		return x;
	else
		return par[x] = find(par[x]);
}
void merge(int x1, int y1) {
	dis = (p[x1].x - p[y1].x) * (p[x1].x - p[y1].x) + (p[x1].y - p[y1].y) * (p[x1].y - p[y1].y);
	x1 = find(x1);
	y1 = find(y1);
	if(x1 == y1)
		return;
	if(rank[x1] < rank[y1] && dis <= d * d)
		par[x1] = y1;
	else if(rank[x1] >= rank[y1] && dis <= d * d){
		par[y1] = x1;
		if(rank[x1] == rank[y1])
			rank[x1]++;
	}
}
bool same(int x, int y) {
	return find(x) == find(y) ? true : false;
}
int main() {
	scanf("%d%d", &n, &d);
	init();
	char ch;
	for(int i = 1; i <= n; i++) {
		scanf("%d%d", &p[i].x, &p[i].y);
	}
	while(~scanf("%c", &ch)) {
		if(ch == 'O') {
			int k;
			scanf("%d", &k);
			vis[k] = 1;
			for(int i = 1; i <= n; i++) {
				//不在一个集合里并且已经被修好了 
				if(!same(i, k) && i != k && vis[i] == 1) {
					merge(i, k);
				}
			}
		}
		else if(ch == 'S'){
			int p, q;
			scanf("%d%d", &p, &q);
			if(same(p, q))
			//在同一个集合里 
				printf("SUCCESS\n");
			else
				printf("FAIL\n");
		}
	}	
	return 0;
} 
게시 44 개 원래 기사 · 원의 칭찬 0 · 조회수 845

추천

출처blog.csdn.net/Komatsu_1137/article/details/104051215