时间:2016-03-17 15:01:10 星期四
题目编号:[2016-03-17][POJ][1308][Is It A Tree]
题目大意:给定若干条边,问这些边是否组成树
分析:并查集合并边,如果遇到不能合并(祖宗节点一样),就不是树
方法:
- 注意空树的情况
- 给出的边号不一定按1~n的顺序,需要vis 做标记,不过这题数据比较水,maxn== 1000,就A了,刚开始vis数组忘记初始化
#include <cstdio>#include<cstring>using namespace std;typedef long long LL;#define CLR(x,y) memset((x),(y),sizeof((x)))#define FOR(x,y,z) for(int (x)=(y);(x)<(z);++(x))const int maxn = 1000;int fa[maxn],mrank[maxn],vis[maxn];void ini(int n){ CLR(mrank,0); CLR(vis,0); FOR(i,0,n + 1){ fa[i] = i; }}int fnd(int x){ return x == fa[x]?x:fa[x] = fnd(fa[x]);}int uni(int x,int y){ x = fnd(x); y = fnd(y); if(x == y) return 0; if(mrank[x] > mrank[y]){ fa[y] = fa[x]; }else { fa[x] = fa[y]; if(mrank[x] == mrank[y]) ++mrank[y]; } return 1;}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int u,v,flg,cntcase = 0; while(~scanf("%d%d",&u,&v) && ~u && ~v){ //空树 if(!(u + v)){ printf("Case %d is a tree.\n",++cntcase); continue; } ini(maxn - 1); flg = 1; if(flg){ if(uni(u,v)){ vis[v] = vis[u] = 1; } else flg = 0; } while(~scanf("%d%d",&u,&v) && u && v){ if(flg){ if(uni(u,v)){ vis[v] = vis[u] = 1; } else flg = 0; } } //判断不是森林 int cnt = 0; if(flg){ FOR(i,0,maxn){ if(vis[i] && fa[i] == i){ ++cnt; } if(cnt > 1){ flg = 0;break; } } } if(flg) printf("Case %d is a tree.\n",++cntcase); else printf("Case %d is not a tree.\n",++cntcase); } return 0;}