题意:和hdu1272差不多,只不过给出的是有向图,问图中的点是否是一颗树。
还是用并查集合并点,对于一条边,如果连接的两点已经在同一并查集内,则可以直接判否。合并时按边的方向记录点的入度,如果某个点入度大于1也就是某个点有多个父亲节点,则说明不是树。合并时顺便记录合并总次数,最后合并 点数-1 次则是树。
1 #include<stdio.h>
2 #include<string.h>
3
4 int fa[100005],num[100005];
5 bool vi[100005];
6
7 void init(){
8 for(int i=1;i<=100004;i++)fa[i]=i;
9 }
10
11 int find(int x){
12 int r=x,t;
13 while(r!=fa[r])r=fa[r];
14 while(x!=r){
15 t=fa[x];
16 fa[x]=r;
17 x=t;
18 }
19 return r;
20 }
21
22 int main(){
23 int a,b,c=0;
24 while(scanf("%d%d",&a,&b)!=EOF&&a!=-1||b!=-1){
25 printf("Case %d is ",++c);
26 if(a==0&&b==0){printf("a tree.
");continue;}
27 init();
28 memset(num,0,sizeof(num));
29 memset(vi,0,sizeof(vi));
30 bool f=1;
31 int x=find(a),y=find(b),cnt=0,ans=0;
32 if(!vi[a]){
33 cnt++;
34 vi[a]=1;
35 }
36 if(!vi[b]){
37 cnt++;
38 vi[b]=1;
39 }
40 num[b]++;
41 if(num[b]>1)f=0;
42 if(x!=y){
43 fa[x]=y;
44 ans++;
45 }
46 else f=0;
47 while(scanf("%d%d",&a,&b)&&a!=0||b!=0){
48 x=find(a),y=find(b);
49 if(!vi[a]){
50 cnt++;
51 vi[a]=1;
52 }
53 if(!vi[b]){
54 cnt++;
55 vi[b]=1;
56 }
57 num[b]++;
58 if(num[b]>1)f=0;
59 if(x!=y){
60 fa[x]=y;
61 ans++;
62 }
63 else f=0;
64 }
65 if(ans==cnt-1&&f)printf("a tree.
");
66 else printf("not a tree.
");
67 }
68 return 0;
69 }