题目链接:
[POJ 2236]Wireless Network[并查集]
题意分析:
电脑网络全部被破坏了,如今能做的是两个操作:一、修复某个电脑;二、查询两个电脑间能否交流。两台电脑能交流的情况是:两台都被修复了,并且两台相距小于d米或者两台之间能借由其它电脑相互联系
解题思路:
当某台电脑被修复时,遍历所有它能连接到的结点,如果所连接结点是被修复的,就将它归入到同一集合。这样每次查询的时候就是O(1)的查询了。
个人感受:
脑子没转过来,想到查询的时候是dfs。。。。。简直了。。。。嘛,还是染色的时候更新比较合理XD
具体代码如下:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
const int INF = 0x7f7f7f7f;
const int MAXN = 1e3 + 111;
int p[MAXN];
bool repair[MAXN];
double x[MAXN], y[MAXN];
vector<int> G[MAXN]; //记录可达点
double getDis(int a, int b)
{
double dx = x[a] - x[b], dy = y[a] - y[b];
return sqrt(dx*dx + dy*dy);
}
int find(int x)
{
return p[x] == x? x : p[x] = find(p[x]);
}
void unite(int a, int b)
{
a = find(a), b = find(b);
p[a] = b;
}
int main()
{
int n, a, b;
double d;
scanf("%d%lf", &n, &d);
for (int i = 1; i <= n; ++i)
{
p[i] = i;
scanf("%lf%lf", &x[i], &y[i]);
}
for (int i = 1; i <= n; ++i)
for (int j = i + 1; j <= n; ++j)
{
if (getDis(i, j) <= d)
{
G[i].push_back(j);
G[j].push_back(i);
}
}
char op[2];
while (~scanf("%s", op))
{
if (op[0] == 'O')
{
scanf("%d", &a);
repair[a] = 1;
for (int i = 0; i < G[a].size(); ++i) //合并更新点周围被更新的点
{
int v = G[a][i];
if (repair[v]) unite(a, v);
}
}
else
{
scanf("%d%d", &a, &b);
if (find(a) == find(b)) printf("SUCCESS\n");
else printf("FAIL\n");
}
}
return 0;
}