并查集的初步学习
2016-03-23 15:37
337 查看
用一句话描述一下并查集:并查集是用树来表示集合,他把每一个连通分量看做一个集合,其中包含了连通分量中的所有点,其中一个连通分量中的点都有共同的父亲结点。
具体的构造:
1. 初始化,每个点的父节点指向自己。
2. 如果两个点有边,那么就在一个连通分量中,所以指向同一个父节点。
3. 最后所有点都会指向各自的父节点,父节点相同的在一个连通分量中。
基本代码就一行:
上几道入门的题目:
hdu 1213 求连通分量的个数
hdu 1232 求最少需要几条边可以使所有点都连通。也是求出连通分量的个数-1即是答案
hdu 1272
题意:
给出一些边,要求这些边连成一个连通图,并且无环,就是构成一棵生成树
分析:
用并查集做,如果两点在连边的时候,他们的父节点相同,说明他两已经在一个连通图了,而现在又连上一条边,构成环。
题目:hdu 1198
题意:
给出一些图片,图片上水管可以相接的就可以连通,求连通块数。
分析:
可以现根据图片是否可以连通,建一个图,然后再用并查集就好。
具体的构造:
1. 初始化,每个点的父节点指向自己。
2. 如果两个点有边,那么就在一个连通分量中,所以指向同一个父节点。
3. 最后所有点都会指向各自的父节点,父节点相同的在一个连通分量中。
基本代码就一行:
int findfa(int x){return x==fa[x]?x:fa[x]=findfa(fa[x]);}
上几道入门的题目:
hdu 1213 求连通分量的个数
hdu 1232 求最少需要几条边可以使所有点都连通。也是求出连通分量的个数-1即是答案
#include<cstdio> #include<cstring> const int N=1001; int fa ; int findfa(int x){return x==fa[x]?x:fa[x]=findfa(fa[x]);} //int findfa(int x) //{ // while(x!=fa[x])x=fa[x]; //循环也可以 // return x; //} bool vis ; int main() { int n,m; while(~scanf("%d%d",&n,&m)&&n){ for(int i=1;i<=n;i++)fa[i]=i; int u,v; for(int i=0;i<m;i++){ scanf("%d%d",&u,&v); int x=findfa(u),y=findfa(v); if(x!=y)fa[x]=y; } int ans=0; memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++){ if(!vis[findfa(i)])ans++; vis[findfa(i)]=1; } printf("%d\n",ans-1); } return 0; }
hdu 1272
题意:
给出一些边,要求这些边连成一个连通图,并且无环,就是构成一棵生成树
分析:
用并查集做,如果两点在连边的时候,他们的父节点相同,说明他两已经在一个连通图了,而现在又连上一条边,构成环。
//hdu 1272 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N=100002; int fa ; bool vis ; int findfa(int x){return x==fa[x]?x:fa[x]=findfa(fa[x]);} int main() { int u,v; while(~scanf("%d%d",&u,&v)){ if(u==-1&&v==-1)break; if(u==0&&v==0){ //需要注意这里,输出Yes printf("Yes\n");continue; } memset(vis,0,sizeof(vis)); for(int i=0;i<N;i++)fa[i]=i; int x=findfa(u),y=findfa(v); fa[x]=y; vis[u]=vis[v]=1; int t=u; bool flag=1; while(scanf("%d%d",&u,&v)&&(u||v)){ x=findfa(u),y=findfa(v); if(x==y)flag=false; //如果两个点的父结点相同,说明有环 fa[x]=y; vis[u]=vis[v]=1; } if(!flag){ printf("No\n");continue; } x=findfa(t); for(int i=1;i<N;i++){ if(vis[i]&&findfa(i)!=x){ flag=false;break; } } if(flag)printf("Yes\n"); else printf("No\n"); } return 0; }
题目:hdu 1198
题意:
给出一些图片,图片上水管可以相接的就可以连通,求连通块数。
分析:
可以现根据图片是否可以连通,建一个图,然后再用并查集就好。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N=55; int fa[N*N]; int findfa(int x){return x==fa[x]?x:fa[x]=findfa(fa[x]);} int a[][4]={ {1,0,0,1},{1,1,0,0},{0,0,1,1},{0,1,1,0},{1,0,1,0}, {0,1,0,1},{1,1,0,1},{1,0,1,1},{0,1,1,1},{1,1,1,0},{1,1,1,1}}; char g ; int main() { int n,m; while(~scanf("%d%d",&n,&m)){ if(n<0||m<0)break; for(int i=0;i<n;i++)scanf("%s",g[i]); for(int i=0;i<n*m;i++)fa[i]=i; for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ int x=findfa(i*m+j),y; if(j+1<m&&a[g[i][j]-'A'][1]&&a[g[i][j+1]-'A'][3]){ y=findfa(i*m+j+1); if(x!=y)fa[y]=x; } if(i+1<n&&a[g[i][j]-'A'][2]&&a[g[i+1][j]-'A'][0]){ y=findfa((i+1)*m+j); if(x!=y)fa[y]=x; } } } int ans=0; for(int i=0;i<n*m;i++) if(findfa(i)==i)ans++; printf("%d\n",ans); } return 0; }
相关文章推荐
- 面试经验
- IOS开发 - 网络总结(一)
- 设计模式之外观模式
- EF 操作 视频教程
- 文字垂直滚动效果
- 精益生产管理
- Multiply Strings
- Android 最火的快速开发框架XUtils
- 带你快速了解 Beyond Compare
- Facebook广告API系列 Business Manager
- 练习1:第一个程序
- ListView的扩展
- Realsense(四)github上一种提取彩色和深度视频流并转为mat的方案
- Dorothy Lua开发建议
- 微信公众平台测试号
- plsql不安装oracle远程连接数据库
- HDU 5649 DZY Loves Sorting 二分+线段树
- 第三周作业--Word Counter
- 通过内容提供者写联系人
- js原生事件系统与坐标系统