转眼又是一万天没有写题惹,好愧疚,标题里打上自用模板,就是写好惹,自用的啦,不介意取走,也很欢迎修改,但是不接受人身伤害,哼唧,玻璃心。
本题属于并查集中比较简单的。并查集的题目,需要搞明白的就是,什么是结点,哪些节点已在一个集内,什么条件下可以合并就可以了。
题目链接:点击打开链接
本题分析:每次修好的电脑是一个新的结点,遍历其余结点,若距离可以就join一波。
最基本的结点结构:
struct node
{
int pre;
int value;
}p[N];
初始化操作:
void Init(int n)
{
for(int i=0;i<n;i++)
{
p[i]=i;
rank[i]=1;
}
}
find操作:
int find(int x)
{
return x == p[x].pre ? x : find(p[x].pre);
}
带路径压缩的find操作:
int find(int x) //查找根节点
{
int r=x;
while ( pre[r ] != r ) //返回根节点 r
r=pre[r ];
int i=x , j ;
while( i != r ) //路径压缩
{
j = pre[ i ]; // 在改变上级之前用临时变量 j 记录下他的值
pre[ i ]= r ; //把上级改为根节点
i=j;
}
return r ;
}
join操作:
void join(const node p1, const node p2)
{
int root1, root2;
root1 = find(p1.pre);
root2 = find(p2.pre);
if(root1 != root2)
ifjoin条件)
p[root2].pre = root1;
}
带按秩合并的join操作:
void join(int x,int y)
{
x=Find(x);
y=Find(y);
if(x==y)return;
if(rank[x]>=rank[y])
{
p[y]=x;
rank[x]=rank[x]+rank[y];
}else
{
p[x]=y;
rank[y]=rank[y]+rank[x];
}
}