并查集,是否成树,Poj(1308)
思路:
对于每一条新的边的两个端点,是否是属于一颗树,要是的话,就不是一颗树。否则,就合并。
这里要注意的是,不能是森林,我这里WA了两次了。只不过在最后,查看每个节点的祖先是否是同一个就可以了。
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int maxn = 105; int father[maxn]; bool vis[maxn]; int Find_set(int x) { if(x!=father[x]) father[x]=Find_set(father[x]); return father[x]; } void Union(int x,int y) { father[y] = x; } int main() { bool flag; int x,y; int t=0; while(scanf("%d%d",&x,&y),x!=-1) { flag=true; if(x==0&&y==0) { printf("Case %d is a tree.\n",++t); continue; } else { for(int i=0;i<maxn;i++) { father[i] = i; vis[i] = false; } int first = x; vis[x]=vis[y]=true; if(Find_set(x)==Find_set(y)) flag=false; else Union(x,y); while(scanf("%d%d",&x,&y),x!=0) { vis[x]=vis[y]=true; int fx=Find_set(x); int fy=Find_set(y); if(fx==fy) flag=false; else Union(fx,fy); } for(int i=0;i<maxn;i++) { if(vis[i]&&Find_set(first)!=Find_set(i)) { flag=false; break; } } if(flag) printf("Case %d is a tree.\n",++t); else printf("Case %d is not a tree.\n",++t); } } return 0; }