题目链接: 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) 번째 행에서 하나씩 수행되는 작업이있다. 각 행은 두 가지 형식을 다음 중 하나의 작업을 포함 :
- "O를 P '(1 <= p <= N), 컴퓨터 (P)를 복구 방법.
- "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;
}