【并查集专题】
来源:互联网 发布:剑三插件数据库 编辑:程序博客网 时间:2024/05/18 00:50
poj 1308 Is It A Tree?
http://poj.org/problem?id=1308
满足一下条件是树:
(1)只有一个根;
(2)一个入度为0的节点,其他节点入度都为1
第一个用并查集,第二个搞个数组统计下就OK。
我用set来存点,因为这些点在输入中可能出现多次,用set只会存一次,set方便些啦!
#include <cstdio>#include <cstdlib>#include <set>#include <iterator>#define N 10001using namespace std; set<int> s;set<int>::iterator iter; int father[N];int degree[N]; void make_set();int find_set(int x);void unin(int x,int y); int main(){ int i,j,f,a,b,k,zero; bool fail; k = 1 ; while(scanf("%d%d",&a,&b) && (a!= -1 && b != -1)) { /* 空树也是树 */ if( a == 0 && b == 0) { printf("Case %d is a tree.\n",k++); continue; } /* 每组数据都得清空 set容器 */ s.clear(); s.insert(a); s.insert(b); /* 初始化 */ make_set(); unin(a,b); ++degree[b]; while(scanf("%d%d",&a,&b) && (a&&b)) { s.insert(a); s.insert(b); unin(a,b); ++degree[b]; } f = find_set(father[*s.begin()]); zero = 0 ;//统计有几个入度为 0 的点 fail = false; for( iter = s.begin(); iter != s.end(); ++iter) { /* 树的每个点的祖先都一样,否则不是树 */ if(f != find_set(father[*iter])) { fail = true; break; } /* 树不能有入度大于 1的节点,否则不是树 */ if(degree[*iter]>1) { fail = true; break; } else { /* 统计根 */ if(degree[*iter] == 0) ++zero; } } printf("Case %d ",k++); if(fail || zero != 1) { printf("is not a tree.\n"); } else printf("is a tree.\n"); } return 0;} void make_set(){ int i; for(i= 1; i < N; ++i) { father[i] = i; degree[i] = 0; } } int find_set(int x){ int t; if(x != father[x]) father[x] = find_set(father[x]);//路径压缩 return father[x];}/* 因为是树,合并是有方向的 */void unin(int x,int y){ x = find_set(x); y = find_set(y); father[y] = x;}
poj 1611 The Suspects
http://poj.org/problem?id=1611
题目描述:
有很多组学生,在同一个组的学生经常会接触,也会有新的同学的加入。但是SARS是很容易传染的,只要在改组有一位同学感染SARS,那么该组的所有同学都被认为得了SARS。现在的任务是计算出有多少位学生感染SARS了。假定编号为0的同学是得了SARS的。
将每一组第一个同学和每一个同学合并就可以了。采用num[]存储该集合中元素个数,并在集合合并时更新num[]即可。然后找出0所在的集合的根节点x,因此,num[x]就是answer了。
#include<cstdio>using namespace std;const int MAXN=30001;int father[MAXN];int num[MAXN];void make_set(int x){ father[x]=x; num[x]=1;}int find_set(int x){ if(x!=father[x]) father[x]=find_set(father[x]); return father[x];}void union_set(int x,int y){ x=find_set(x); y=find_set(y); if(x==y) return ; father[y]=x; num[x]+=num[y];}int main(){ int n,m,t,x,y; while(scanf("%d%d",&n,&m)){ if(m==0&&n==0) break; if(m==0){ printf("1\n"); continue; } for(int i=0;i<n;i++) make_set(i); for(int i=0;i<m;i++){ scanf("%d",&t); scanf("%d",&x); for(int j=1;j<t;j++){ scanf("%d",&y); union_set(x,y); } } x=find_set(0); printf("%d\n",num[x]); }}
POJ 1703 Find them, Catch them
http://poj.org/problem?id=1703
题意 :有两个不同的帮派,每个帮派至少有一个人。 判断两个人是否属于同一个帮派。
有 T 组测试数据。
给你 N 个人,编号从 1 到 N,操作 M 次。
每次操作输入一个字符和两个数 x ,y
如果字符为 A 则判断 x 和 y 是否属于同一个帮派,并且输出结果。
如果字符为 D 则明确告诉你 x 和 y 是属于不同帮派的。
详细分析:
http://blog.csdn.net/brand__new/article/details/24640381
#include<cstdio>const int maxn = 100000+10;int p[maxn]; //存父亲节点int r[maxn]; //存与根节点的关系,0 代表同类, 1代表不同类int find(int x) //找根节点{ if(x == p[x]) return x; int t = p[x]; //记录父亲节点 方便下面更新r[] p[x] = find(p[x]); r[x] = (r[x]+r[t])%2; //根据子节点与父亲节点的关系和父节点与爷爷节点的关系,推导子节点与爷爷节点的关系 return p[x]; //容易忘记}void Union(int x, int y){ int fx = find(x); //x所在集合的根节点 int fy = find(y); p[fx] = fy; //合并 r[fx] = (r[x]+1+r[y])%2; //fx与x关系 + x与y的关系 + y与fy的关系 = fx与fy的关系}void set(int n){ for(int x = 1; x <= n; x++) { p[x] = x; //自己是自己的父节点 r[x] = 0; //自己和自己属于同一类 }}int main(){ int T; int n, m; scanf("%d", &T); while(T--) { scanf("%d%d%*c", &n, &m); set(n); char c; int x, y; while(m--) { scanf("%c%d%d%*c", &c, &x, &y); //注意输入 //printf("%c\n", c); if(c == 'A') { if(find(x) == find(y)) //如果根节点相同,则表示能判断关系 { if(r[x] != r[y]) printf("In different gangs.\n"); else printf("In the same gang.\n"); } else printf("Not sure yet.\n"); } else if(c == 'D') { Union(x, y); } } } return 0;}
0 0
- 并查集专题
- 【并查集专题】
- 并查集专题
- 并查集专题学习
- 并查集专题【完结】
- 【并查集专题】【HDU】
- 并查集专题练习(一)POJ1611
- 数据结构专题小结:并查集
- 并查集专题-1001 Freckles
- 【各大OJ】并查集专题
- 并查集专题训练解题报告
- 并查集专题: HDU1232畅通工程
- 【并查集入门专题1】F
- 【并查集入门专题1】E
- 2014级寒假特训之并查集专题
- kuangbin带你飞 专题五 并查集
- [kuangbin带你飞]专题五 【并查集】 【--完结--】
- LeetCode Union-Find(并查集) 专题(一)
- 新的起点
- 阿姆斯特朗数 软件训练营 初级 入职前练习 C/C++
- 带有武器发射子弹的游戏主界面
- shell用户手册
- EXCEL:批量读取EXCEL文件给指定数据库(access,sql server)
- 【并查集专题】
- ubuntu12.10安装myeclipse10.5 以及破解
- 面试经之给刚毕业的大学生和刚入门的程序员的忠告及图书推荐
- pull解析xml
- Xlib: connection to ":0.0" refused by server
- Java中的深拷贝(深复制)和浅拷贝(浅复制)
- 使用Truetype字体制作ArcGIS符号
- 九度OJ 1537:买卖股票
- “隐写术”的趋势