poj1308(并查集)
Posted frankchen831x
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了poj1308(并查集)相关的知识,希望对你有一定的参考价值。
题目链接:http://poj.org/problem;jsessionid=436A34AE4BE856FB2DF9B264DCA9AA4E?id=1308
题意:给定一些边让你判断是否构成数。
思路:这道题细节很多,wa了好久。利用并查集将一棵树的节点并在一块,如果当前的边的两个端点祖先相同,则不能够成树(有环),利用num数组记录每个结点的入度,入度不能大于1。输入为 0 0表示空树,满足条件。可能出现森林,所以用vector记录出现的结点编号,最后判断所有结点是否有相同的祖先。还有不能存在i i,即指向自己的边。
AC代码:
#include<cstdio> #include<vector> using namespace std; const int maxn=1e6+5; int root[maxn],num[maxn],t1,t2,flag,cas=1; vector<int> v; int getr(int k){ if(root[k]==k) return k; else return root[k]=getr(root[k]); } int main(){ while(~scanf("%d%d",&t1,&t2)&&t1>=0){ if(!t1){ printf("Case %d is a tree. ",cas++); continue; } v.clear(); v.push_back(t1); v.push_back(t2); for(int i=1;i<=1000000;++i) root[i]=i,num[i]=0; flag=1; if(t1==t2) flag=0; int r1=getr(t1),r2=getr(t2); root[r2]=r1,++num[t2]; while(~scanf("%d%d",&t1,&t2)&&t1){ if(flag){ v.push_back(t1); v.push_back(t2); r1=getr(t1),r2=getr(t2); if(r1!=r2&&!num[t2]&&t1!=t2) root[r2]=r1,++num[t2]; else flag=0; } } if(flag){ int r=getr(v[0]); for(int i=1;i<v.size();++i) if(getr(v[i])!=r){ flag=0; break; } } if(flag) printf("Case %d is a tree. ",cas++); else printf("Case %d is not a tree. ",cas++); } return 0; }
以上是关于poj1308(并查集)的主要内容,如果未能解决你的问题,请参考以下文章
POJ-1308 Is It A Tree?(并查集判断是否是树)