Is It A Tree?——简单并查集应用
Posted j666
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Is It A Tree?——简单并查集应用相关的知识,希望对你有一定的参考价值。
题意:
判断所给的数据能否构成一颗树。
题解:
题目中所给的是有向树,并给出了性质:
1.只有一个节点,称为根节点,没有定向边指向它。
2.除了根节点外,每个节点都只有有一条指向它的边。
3.从树根到任一结点有一条有向通路。
抽象过来就是三个条件:
1.只有一个入度为0的点,作为根节点。
2.除根节点外,其他点的入度只能为1。
3.所有点都能连通,也就是所有点需要在一个集合中,使用并查集来划分集合。
注意!!!可能会出现空树,也就是0 0,空树也是树。
代码:
#include<iostream> #include<stdio.h> #include<math.h> #include<algorithm> #include<vector> #include<cstring> using namespace std; typedef long long ll; const int maxn = 2e5+7; int f[maxn],d[maxn],vis[maxn],in[maxn]; int a,b; int Find(int x) return f[x]==x?x:f[x]=Find(f[x]); void join(int x,int y) int fx=Find(x); int fy=Find(y); if(fx!=fy) f[fy]=fx; int main() int Case=1; while(~scanf("%d%d",&a,&b)) if(a==-1 && b==-1)break; for(int i=0; i<maxn; i++)f[i]=i,in[i]=0,vis[i]=0; if(a==0 && b==0) printf("Case %d is a tree.\n",Case++); continue; vis[a]=1; vis[b]=1; in[b]++; join(a,b); while(~scanf("%d%d",&a,&b)) if(a==0 && b==0)break; vis[a]=1; vis[b]=1; in[b]++; join(a,b); int flag=1; int root=0; int cnt=0; for(int i=1;i<maxn;i++) if(vis[i] && in[i]==0)root++;///根节点个数 if(in[i]>=2)flag=0;///除了根节点外,其他点入度为1 if(vis[i] && f[i]==i)cnt++;///判断所有点是否都在一个集合 if(root!=1 || cnt>1)flag=0; if(flag)printf("Case %d is a tree.\n",Case++); else printf("Case %d is not a tree.\n",Case++); return 0;
以上是关于Is It A Tree?——简单并查集应用的主要内容,如果未能解决你的问题,请参考以下文章