树的判定两道题
1.判断有向图是否是树
POJ 1308 --- Is It A Tree ?
题目链接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=39051#problem/G
有向图是否为树的判断条件:
1.树中每个节点至多只能有一个父节点。
2.树中不能出现环。
3.树中只能有一个根节点。
用并查集来解,则条件转化为:
1'.一个节点要连接到另一个节点的后面,则该节点必须是根节点,否则会出现两个根节点的情况。
2'.如果两个节点已经属于同一个集合,则不能在合并,否则会出现环。
3'.最后统计根节点(fa[i] == i)的个数,如果大于一个,则不是树。
代码:
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> using namespace std; #define N 1000100 int fa[N],flag[N]; void makeset(int n) { for(int i=1;i<=n;i++) { fa[i] = i; flag[i] = 0; } } int findset(int x) { if(x != fa[x]) { fa[x] = findset(fa[x]); } return fa[x]; } int unionset(int a,int b) { int x = findset(a); int y = findset(b); //b永远是a的子节点 if(x == y) //已经是一个集合,再合并会形成环 return 1; if(fa[y] != b) //b不是根节点 return 1; else { fa[y] = x; return 0; } } int main() { int a,b,i,maxi,gen,bad; int cs = 1; bad = 0; maxi = 0; makeset(N-1); while(1) { scanf("%d%d",&a,&b); if(a == -1 && b == -1) break; maxi = max(maxi,max(a,b)); if(a == 0 && b == 0) { gen = 0; for(i=1;i<=maxi;i++) { if(flag[i] == 1 && fa[i] == i) //是否根节点 { gen++; } if(gen>1) break; } if(gen>1 || bad>0) printf("Case %d is not a tree.\n",cs++); else printf("Case %d is a tree.\n",cs++); bad = 0; maxi = 0; makeset(N-1); } else { flag[a] = flag[b] = 1; bad += unionset(a,b); } } return 0; }
作者:whatbeg
出处1:http://whatbeg.com/
出处2:http://www.cnblogs.com/whatbeg/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
更多精彩文章抢先看?详见我的独立博客: whatbeg.com