UVA10608 Friends 题解
实际上,带权并查集的几种操作并不复杂,是基础并查集的扩展版。PS:第一篇题解,若有不慎指出敬请谅解。本人太弱,就用带权并查集做。数组遍历一遍,找最大值即可。(不省略常数与低次项)读完题就知道,这题用。这些操作实现完毕后,
·
0x01 STEP1 读题审题
读完题就知道,这题用并查集。
本人太弱,就用带权并查集做。
0x02 STEP2 主要步骤
实际上,带权并查集的几种操作并不复杂,是基础并查集的扩展版。
初始化:
for(int i=1;i<=n;i++)
{
f[i]=i;
num[i]=1; //注意这一行,num[i]表示以i为根节点的集合有多少元素
}
递归找祖宗:
int getf(int x)
{
if(f[x]==x)return x; //和基础并查集没什么区别
int k=getf(f[x]);
f[x]=k; //路径压缩,降低复杂度
return f[x];
}
合并:
int merge(int x,int y)
{
int p1=getf(x);
int p2=getf(y);
if(p1!=p2) //如果不属于同一集合,则合并
{
f[p2]=f[p1];
num[p1]+=num[p2]; //合并后,要把小集合的元素数量加到大集合里
}
return 0;
}
这些操作实现完毕后, O ( n ) O(n) O(n)把 n u m [ i ] num[i] num[i]数组遍历一遍,找最大值即可。
0x03 STEP3 复杂度分析
初始化 O ( n ) O(n) O(n)
并查集最坏 O ( m l o g n ) O(mlogn) O(mlogn)
找最大值 O ( n ) O(n) O(n)
一次操作大约 O ( m l o g n + 2 n ) O(mlogn+2n) O(mlogn+2n)(不省略常数与低次项)
代入计算得约等于 2000000 2000000 2000000 A C AC AC没问题
0x04 STEP4 完整代码
#include <bits/stdc++.h>
using namespace std;
int n,m,t,f[300000],num[300000];
int getf(int x)
{
if(f[x]==x)return x; //和基础并查集没什么区别
int k=getf(f[x]);
f[x]=k; //路径压缩,降低复杂度
return f[x];
}
int merge(int x,int y)
{
int p1=getf(x);
int p2=getf(y);
if(p1!=p2) //如果不属于同一集合,则合并
{
f[p2]=f[p1];
num[p1]+=num[p2]; //合并后,要把小集合的元素数量加到大集合里
}
return 0;
}
int main() //请从主函数开始阅读程序,这是个好习惯
{
scanf("%d",&t);
for(int q=0;q<t;q++)
{
int maxn=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
f[i]=i;
num[i]=1; //注意这一行,num[i]表示以i为根节点的集合有多少元素
}
for(int i=1;i<=m;i++)
{
int j,p;
scanf("%d%d",&j,&p);
merge(j,p); //合并操作
}
for(int i=1;i<=n;i++) //遍历num数组找最大值
if(num[i]>maxn)maxn=num[i];
printf("%d\n",maxn);
}
return 0;
}
0x05 STEP5 扩展训练
T h e The The E n d End End
PS:第一篇题解,若有不慎指出敬请谅解。
更多推荐
所有评论(0)