题目:
#include<iostream>
#include<vector>
using namespace std;
const int N=1002;
int father[N]; //记录i的根节点
int d; //通信最大距离
void init(int n)
{
for(int i=0;i<=n;i++){
father[i]=i;
}
}
int find(int x)
{
return father[x]==x?x:father[x]=find(father[x]);
}
void merge(int a, int b,vector<vector<int> >&dist)
{
int roota=find(a),rootb=find(b);
if(roota!=rootb){
int s=(dist[a][0]-dist[b][0])*(dist[a][0]-dist[b][0])+((dist[a][1]-dist[b][1]))*((dist[a][1]-dist[b][1]));
if(s<=d*d)
father[rootb]=roota;
}
}
int main()
{
int n;
scanf("%d%d",&n,&d);
init(n);
vector<vector<int> >dist(n+1,vector<int>(2,0)); //记录电脑坐标
for(int i=1;i<=n;i++){
scanf("%d%d",&dist[i][0],&dist[i][1]);
}
vector<int>Cmps; //记录修好了的电脑
char ope;
while(getchar()&&scanf("%c",&ope)!=EOF){
if(ope=='O'){
int p;
scanf("%d",&p);
for(int i=0;i<Cmps.size();i++){
merge(Cmps[i],p,dist);
}
Cmps.push_back(p);
}
else{
int p,q;
scanf("%d%d",&p,&q);
if(find(p)==find(q))
printf("SUCCESS\n");
else
printf("FAIL\n");
}
}
return 0;
}
大概思路:
将修的电脑与已经修好的电脑进行合并操作建立联系,如果两个电脑不在同一集合中且两个电脑可以直接通信,则将两个电脑并入同一个集合中。在同一集合中的电脑表示可以直接或者间接的进行通信,所以判断两个电脑能不能进行通信,判断两个电脑在不在同一集合即可。
并查集四部曲:
①确定father和weight数组含义:(这里用不着weight数组就不写了)
int father[N]; //记录i的根节点
②初始化:
father[i]=i;
③确定路径压缩方式:
father[x]=find(father[x]);
④确定合并方式:
if(roota!=rootb){
int s=(dist[a][0]-dist[b][0])*(dist[a][0]-dist[b][0])+((dist[a][1]-dist[b][1]))*((dist[a][1]-dist[b][1]));
if(s<=d*d)
father[rootb]=roota;}