poj 2236

思路:初始时各个节点与自己都不连通,所以pre值为-1,每进行一次O操作,就先把点A的pre值设为自己,然后遍历在d范围内的所有点把它们联通。

坑点:

1、注意O是字母O,而不是0

2、因为初始值为-1,所以假如查询一个没有进行过O操作的点时,不加特判会死循环

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

const int N = 1010;

int pre[N];
struct Point{
	double x, y;
};

double cal_dis(Point p1, Point p2){
	return (sqrt((p1. x - p2. x) * (p1. x - p2. x) + (p1. y - p2. y) * (p1. y - p2. y)));
}

int find(int x){
	int r = x;
	while(pre[r] != r){
		if(pre[r] == -1)
			return -1;
		r = pre[r];
	}
	int i = x, j;
	while(i != r){
		j = pre[i];
		pre[i] = r;
		i = j;
	}
	return r;
}

void join(int x, int y){
	int t1 = find(x), t2 = find(y);
	if(t1 != t2){
		pre[t2] = t1;
	}
}

int main(){
	int n, d;
	scanf("%d%d", &n, &d);
	Point p[N];
	for(int i = 1; i <= n; i ++){
		scanf("%lf%lf", &p[i]. x, &p[i]. y);
	}
	memset(pre, -1, sizeof(pre));
	char c;
	while(cin >> c){
		int a, b;
		if(c == 'O'){
			scanf("%d", &a);
			pre[a] = a;
			for(int i = 1; i <= n; i ++){
				if(pre[i] != -1){
					if(cal_dis(p[a], p[i]) <= d){
						join(a, i);
					}
				}					
			}
		}
		else{
			scanf("%d%d", &a, &b);
			int x1 = find(a), x2 = find(b);
			if(x1 == -1 || x2 == -1)
				cout << "FAIL" << endl;
			else{
				if(find(a) == find(b))
					cout << "SUCCESS" << endl;
				else
					cout << "FAIL" << endl;
			}
		}
	}	
	return 0;
}
ps:这东西比最短路简单多了,那几个算法的证明简直恐怖(꒪Д꒪)ノ

猜你喜欢

转载自blog.csdn.net/qq_38759433/article/details/80168997
今日推荐