暑假啦,做并查集专题~~~~
思路:
- 先预处理把距离合格的电脑之间做上标记。
- 每次修理时可能发生合并。
- 每次询问时,查看是否在同一组中。
注意:
- 不加头文件可能会莫名报错。
- scanf 注意加 getchar。
- 写递归的 FIND 即可,不需要写递推。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1005;
int N,D;
struct NODE{
int x;
int y;
bool ok;
};
NODE node[maxn];
bool mp[maxn][maxn];
int par[maxn];
int CAL(int i,int j){
int X = (node[i].x - node[j].x)*(node[i].x - node[j].x);
int Y = (node[i].y - node[j].y)*(node[i].y - node[j].y);
return X + Y;
}
void INIT(){
memset(par , -1 , sizeof(par));
return ;
}
int FIND(int i){
return par[i] == -1 ? i : par[i] = FIND(par[i]);
}
void UNION(int l,int r){
int parl = FIND(l) ;
int parr = FIND(r) ;
if(parl != parr)
par[parl] = parr;
return ;
}
int main(){
memset(mp , 0 , sizeof(mp));
scanf("%d%d" , &N , &D);
INIT();
for(int i=1;i<=N;i++){
scanf("%d%d" , &node[i].x , &node[i].y);
node[i].ok = false;
}
for(int i=1;i<=N;i++){
for(int j=1;j<=N;j++){
if(i == j)
mp[i][j] = true;
else{
if(CAL(i , j) <= D*D)
mp[i][j] = mp[j][i] = true;
}
}
}
getchar();
char c;
while(~scanf("%c" , &c)){
getchar();
int l,r;
if(c == 'O'){
scanf("%d" , &l);
node[l].ok = true;
for(int i=1;i<=N;i++){
if(l!=i && mp[l][i] && node[i].ok)
UNION(l , i);
}
}
else{
scanf("%d%d" , &l , &r);
if(FIND(l) == FIND(r))
printf("SUCCESS\n");
else
printf("FAIL\n");
}
getchar();
}
return 0;
}
- 递推的 FIND 函数:3032ms 1680kB
int FIND(int i){
int root = i;
while(par[root] != -1)
root = par[root];
while(i != root){
par[i] = root;
i = par[i];
}
return root;
}