HDU-1325-Is It A Tree?

题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1325

程序分析:

  这道题跟小希的迷宫有很大的相似吧,只是一个是无向图一个是有向图。也是给你那些结点之间的信息,然后让你判断是不是一颗树罢了,用树的定义来判断吧,无环,n个结点最多有n-1条边,不然就会有环。只有一个入度为0的结点,不存在入度大于1的结点。这些也足以判断是否为一棵树了吧。不过要注意一些特殊数据的情况,空树也是树。比如输入0 0。

解决方法:

  其实也可以不用并查集,这样就可以直接按照上面的条件来统计,就可以判断是不是一颗树了。方法有多种,都知道最好,但是得精通,这些天都是在练并查集,所以我就用了并查集的思想来做吧,我加了个条件判断就是判断他村不存在环,这个是用到:如果两个不同的结点的根结点都相同,这样就会存在一个环或者有一个结点的入度会变为2了。只好也就不符合树的定义了。

  控制输入数据时有点坑爹,输入停止条件应该是 a < 0 || b < 0,因为这个WA了很多次,最后是老大帮我改了之后就A了,一直还以为是数组不够大或者输入函数那些没写好,原来就是这么一个小BUG。学东西吧,错的多,改对了就能学会多一点。

 

 

View Code
 1 #include<iostream>
 2 using namespace std;
 3 
 4 const int Max = 100000+10;
 5 int Far[Max];
 6 int Rank[Max]; //改为标记结点的入度
 7 int Sign[Max];
 8 
 9 void Make_set(int n)
10 {
11     int i;
12     for(i=0; i<n; i++)
13     {
14         Far[i] = i;
15     }
16     memset(Rank, 0, sizeof(Rank));
17     memset(Sign, 0, sizeof(Sign));
18 }
19 
20 int Find_set(int x)
21 {
22     if(Far[x] != x)
23         return Far[x] = Find_set(Far[x]);
24     return Far[x];
25 }
26 
27 void Unio(int a, int b)
28 {
29     a = Find_set(a);
30     b = Find_set(b);
31     if(a == b)
32         return;
33     //因为是有向图,合并方向必须只有一个
34     Far[b] = a;
35     /*
36     if(Rank[a] < Rank[b])
37         Far[a] = b;
38     else if(Rank[a] > Rank[b])
39         Far[b] = a;
40     else 
41     {
42         Far[a] = b;
43         Rank[b]++;
44     }*/
45 }
46 
47 int main()
48 {
49     int a, b;
50     //初始化
51     int flag = 1;
52     int k = 1;
53     Make_set(Max);
54     while(cin>>a>>b )
55     {
56         if(a < 0 || b < 0)
57             return 0;
58         if(a == 0  && b == 0) //待一组数据输入完毕后才输出结果
59         {
60             int ans = 0;
61             for(int i=1; i<Max; i++)
62             {
63                 if(Sign[i] && Find_set(i) == i)  //统计有几个连通分支
64                     ans++;
65                 if(Rank[i] > 1)  //存在有入度大于一的结点就不是树了,是图
66                 {
67                     flag = 0;
68                     break;
69                 }
70             }
71             if(ans > 1)  //连通分支大于1,表示是否为森林
72                 flag = 0;
73             if(flag)
74                 cout<<"Case "<<k++<<" is a tree."<<endl;
75             else
76                 cout<<"Case "<<k++<<" is not a tree."<<endl;
77             //从新初始化
78             flag = 1; //表示为Yes
79             Make_set(Max);
80             continue;
81         }
82         if(a != b && Find_set(a) == Find_set(b))  //根节点相同,但叶子不同,表示a,b已存在路径,如果
83         {                                          //仍增加一条路径则会存在环,则有第二天路径
84             //cout<<"No"<<endl;
85             flag  = 0;
86         }
87         else
88         {
89             Sign[a] = 1;
90             Sign[b] = 1;
91             Rank[b] ++;  //入度加一
92             Unio(a, b);  //b的老大是a,只能是一个方向,因为是有向图
93         }
94     }
95     return 0;
96 }

 

posted @ 2012-08-26 12:01  另Ⅰ中Feel▂  阅读(835)  评论(0编辑  收藏  举报