并查集题集(一)
来源:互联网 发布:淘宝卖家星级 编辑:程序博客网 时间:2024/06/17 18:48
/*HDU 1213 算是并查集入门题吧题意,思路都没什么说的 ...*/ #include<iostream>#include<cstdio>using namespace std;#define manx 1009int p[manx];int root(int a){ int temp = a; for( ; p[a]!=a; a=p[a] ) ; /// 查找根节点 while( temp!=a ){ /// 压缩路径 int x=p[temp]; p[temp] = a; temp = x; } return a;}int main(){ int t,m,n; scanf("%d",&t); while(t--){ cin>>n>>m; for(int i=1;i<=n;i++) p[i]=i; int a,b; while(m--){ cin>>a>>b; a = root(a); b = root(b); p[b] = a; /// 合并路径 } int flag=0; for(int i=1;i<=n;i++) if(p[i]==i) flag++; cout<<flag<<endl; }}
/*HDU 1272 题意:中文 思路:当两个根节点是一样的话,那一定存在环...数据:0 0 是一个空树,要输出 Yes */#include<iostream>#include<cstdio>using namespace std;#define manx 100009int p[manx],s[manx];int root(int x){ int temp = x; for( ; p[x]!=x; x=p[x]) ; while(temp!=x){ int i=p[temp]; p[temp] = x; temp = i; } return x;}int main(){ int a,b; while(1){ int flag=0,mark=0,k=0; for(int i=0;i<manx;i++) p[i]=i,s[i]=0; while(1){ scanf("%d%d",&a,&b); if(a==0 && b==0 && k==0) { cout<<"Yes"<<endl; flag=2; break; } /// 空树 if(a==0 && b==0) break; s[a]=s[b]=1; if(a==-1 && b==-1) { flag=1; break; } int a1 = root(a); int b1 = root(b); if(a1==b1) mark=1; /// 标记看是否会有环出现 ... p[b1] = a1; k++; } if(flag==1) break; if(flag==2) continue; if(mark) { cout<<"No"<<endl; continue; } for(int i=1;i<manx;i++) if(s[i]&&p[i]==i) flag++; if(flag==1) cout<<"Yes"<<endl; else cout<<"No"<<endl; }}
/*POJ 1308 思路:并查集注意:每个节点的入度小于或者等于 1 ... */#include<iostream>#include<cstdio>using namespace std;#define manx 100009int p[manx],s[manx];int root(int x){ int temp = x; for( ; p[x]!=x; x=p[x]) ; while(temp!=x){ int i=p[temp]; p[temp] = x; temp = i; } return x;}int main(){ int a,b,ca=0; while(1){ ca++; int flag=0,mark=0,k=0; for(int i=0;i<manx;i++) p[i]=i,s[i]=0; while(1){ scanf("%d%d",&a,&b); if(a==0 && b==0 && k==0) { printf("Case %d is a tree.\n",ca); flag=2; break; } if(a==0 && b==0) break; s[a]=s[b]=1; if(a==-1 && b==-1) { flag=1; break; } int a1 = root(a); int b1 = root(b); if(a1!=a && b1!=b) mark=1; /// 要构成树,那么每个点的入度是 1,所以不可以两个点同时有不同于自己的祖先 if(a1==b1 || a==b) mark=1; p[b1] = a1; k++; } if(flag==1) break; if(flag==2) continue; if(mark) { printf("Case %d is not a tree.\n",ca); continue; } for(int i=1;i<manx;i++) if(s[i]&&p[i]==i) flag++; if(flag==1) printf("Case %d is a tree.\n",ca); else printf("Case %d is not a tree.\n",ca); }}
/*HDU 1856 思路:目测了一下数据,直接做可能会超时,所以现对数据处理一下,进行一个离散化 离散化 + 并查集 + 记录单点值 */#include<iostream>#include<cstdio>#include<algorithm>using namespace std;#define manx 100009int p[manx],a[manx<<1],rank[manx<<1],x[manx<<1],val[manx<<1];bool comp(const int &i,const int &j){ return a[i]<a[j] || i==j && a[i]==a[j];}int root(int x){ int temp=x; for( ; p[x]!= x; x=p[x] ) ; while(temp!=x){ int ans = p[temp]; p[temp] = x; temp = ans; } return x;}int main(){ int n; while(cin>>n){ if(n==0) { cout<<"1"<<endl; continue; } for(int i=0;i<=2*n;i++) p[i]=i,val[i]=1; for(int i=1;i<=n;i++){ scanf("%d%d",&a[2*i-1],&a[2*i]); rank[2*i-1]=2*i-1; rank[2*i]=2*i; } //// 以下是对数据离散化处理 ///////////////////////////////////// sort(rank+1,rank+2*n+1,comp); x[rank[1]]=1; int ans = 1; for(int i=2;i<=2*n;i++){ if(a[rank[i]]!=a[rank[i-1]]){ x[rank[i]]= ++ans; } else x[rank[i]]=ans; } ////////////////////////////////////// for(int i=1;i<=n;i++){ int a1 = root(x[2*i-1]); int b1 = root(x[2*i]); if(a1!=b1){ p[b1] = a1; val[a1] += val[b1]; } } int max=-1; for(int i=1;i<=2*n;i++) if(max<val[i]) max = val[i]; cout<<max<<endl; }}
/*HDU 1232 并查集 */#include<iostream>#include<cstdio>using namespace std;#define manx 1100int p[manx];int root(int x){ int temp = x; for(; p[x]!=x; x=p[x] ); while(temp!=x){ int t=p[temp]; p[temp] = x; temp = t; } return x;}int main(){ int n,m; while(scanf("%d",&n),n){ scanf("%d",&m); int st,ed; for(int i=1;i<=n;i++) p[i]=i; for(int i=1;i<=m;i++){ cin>>st>>ed; int a = root(st); int b = root(ed); if(a!=b) p[b] = a; } int flag=-1; for(int i=1;i<=n;i++) if(p[i]==i) flag++; cout<<flag<<endl; }}
/*HDU 1811 并查集 + 拓扑排序 这道题给我的直觉,貌似主要还是考察拓扑排序,思路:相等的点(使用并查集)放到一个集合中去, 然后把所有入度为零的点放到队列中去,如果que.size()>1,说明有多种排序这道题还是用了链表 ...同一条链上说明全是和主元直接相连的...神牛题解:http://972169909-qq-com.iteye.com/blog/1052820 */ #include<iostream>#include<cstdio>#include<queue>#define manx 10009using namespace std;int p[manx],a[manx<<1],b[manx<<1],ind[manx];char ch[manx<<1];int n,m;queue<int>que;struct node{ int son; node *next;}*N[manx];void init(){ for(int i=0;i<=n;i++){ p[i]=i,a[i]=b[i]=0; ind[i] = 0; N[i]=NULL; } while(!que.empty()) que.pop();}void insert(int a,int b){ // b 插入作为 a 的儿子,这条链上全部都是 a 的儿子 node *p = new node; p->son = b; p->next = N[a]; N[a] = p;}int root(int x){ // 并查集 int temp = x; for( ; p[x]!=x; x=p[x]) ; while(temp!=x){ int t = p[temp]; p[temp] = x; temp = t; } return x;}int main(){ while(cin>>n>>m){ init(); int num=n; for(int i=0;i<m;i++){ scanf("%d %c %d",&a[i],&ch[i],&b[i]); if(ch[i]=='='){ int a1=root(a[i]); int b1=root(b[i]); if(a1!=b1) p[b1]=a1, num--; } } int flag = 0; for(int i=0;i<m;i++){ if(ch[i]=='=') continue; int aa = root(a[i]); int bb = root(b[i]); if(a[i]==b[i]){ flag = 1; break; } if(ch[i]=='>'){ insert(aa,bb); ind[bb]++; } else { insert(bb,aa); ind[aa]++; } } if(flag) { cout<<"CONFLICT"<<endl; continue; } for(int i=0;i<n;i++) if(ind[i]==0 && i == root(i)) /// 找到入度为 0,并且自身是根节点,加入队列 que.push(i); while(!que.empty()){ if(que.size()>1) flag=1; /// 说明排序有多种情况,信息不全 int t = que.front(); que.pop(); num--; for(node*i = N[t]; i; i = i->next) /// 把这条链上所有入度为 0 的全部加进队列 if(--ind[i->son] == 0) que.push(i->son); } if(num>0) cout<<"CONFLICT"<<endl; else if(flag) cout<<"UNCERTAIN"<<endl; else cout<<"OK"<<endl; }}/*3 30 > 11 < 20 > 24 41 = 21 > 32 > 00 > 13 31 > 01 > 22 < 1*/
- 并查集题集(一)
- 并查集的应用(一)
- Redis学习(一)安装并测试
- 并查集总结(一)
- nyoj 一笔画(并查集)
- 安装并配置ROS环境(一)
- 一.快速并查集(Union_Find)
- 一笔画问题(nyoj42)(并查集+欧拉图)
- 怎么编写并注册Gstreamer插件(一)
- C#动态生成Word文档并填充数据(一)
- API SOCKET基础(一) TCP建立连接并通信
- API SOCKET基础(一) TCP建立连接并通信
- java swing (一) 导出excel文件并打开
- API SOCKET基础(一) TCP建立连接并通信
- 一、并查集 (Union-Find Set)
- nyist 42一笔画问题(并查集+欧拉图)
- 搭建Ubuntu14.04编译环境并下载源码(一)
- 并查集学习---系统整理(一)
- MVC4 Web Api 与 Ajax交互存在的跨域问题总结
- 关于node的shell---#!/usr/bin/env node
- Apache Thrift 介绍
- Source Insight的设置:将函数名的字体设置为大号字体,加粗,醒目,方便阅读
- ORA-01552 cannot use system rollback segment for non-system tablespace
- 并查集题集(一)
- 会话管理
- 二叉树非递归的后序前序中序遍历
- 窗口关闭过程,非模态对话框为什么不能使用enddialog关闭窗口
- java web的知识点总结
- 事务实例(基于Mysql)
- oracle flash table
- TBODY的解释和用法
- 【曾国藩语录】