Copy (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)
10 9 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 1 10 10 4 2 3 4 5 4 8 5 8 0 0
Case 1: 1 Case 2: 7
数据量巨大,C++程序推荐用 scanf
#----------------------------------------------------------------------------------------------#
写这道题并不是想说什么思路,主要是想记录一个惊天地泣鬼神的东西(这一点也不夸张……)
很多时候并查集需要找集合的个数(比如这道题),所以,我们应该怎么办呢?
我的第一次方法是:
找每一个结点的根,用一个bool数组记录,有一个新的就sum++:
for(int i=1;i<=n;i++)if(!ans[father[i]]){ans[father[i]]=1;sum++;}
所以,我发现了一个方法(尽管很容易想到,然而我没有):
直接数根结点个数!
我一下子就觉悟了……
反正我的根结点标记是-1,就这样即可:
for(int i=1;i<=n;i++)if(father[i]==-1)sum++;
代码:
#include<cstdio>
#include<cstring>
int father[50005];
int n,m,k;
int root(int x)
{if(father[x]==-1)return x;//找到根father[x]=root(father[x]);//找的时候路径压缩,路径压缩是什么?简单说就是使一个集合的除根结点以外所有点的father都变为根结点return father[x];
}
int main()
{while(1){scanf("%d%d",&n,&m);if(!n&&!m) return 0;memset(father,-1,sizeof(father));//默认每个数都是根结点for(int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);int rx=root(x),ry=root(y);if(rx!=ry)//两个数不在一个集合father[ry]=rx;//就合并}int sum=0;for(int i=1;i<=n;i++)if(father[i]==-1)sum++;//刚刚说的方法printf("Case %d: %dn",++k,sum);}
}
转载于:.html
本文发布于:2024-02-02 03:06:42,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170681611440994.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |