【包教包會】用樹的定義去判斷樹!(HDU1272)(HDU1325)(POJ1308)

標題這幾題都是去判斷樹的,只是輸出不一樣

要用定義去做樹,那肯定要知道樹是什麼
學習的時候很迷茫是沒搞清楚大方向
什麼是大方向呢?
兩個字:圖論
樹肯定是圖,但圖不一定是樹
搞清楚這麼幾個知識點就可以愉快的做這題了

  • 什麼是度?度就是邊。度分爲入度和出度(出邊和入邊)。我們這裏有個點V,指向V的邊就是入度,從V指出去的是出度
  • 什麼是樹?只有一個點入度爲0,其它點入度爲1的圖就是樹。

好了,一旦解決了什麼是樹,那所有問題解決了。什麼?你說還不懂?那我給你一個個列出來

  1. 只有一個點入度爲0保證了樹有且只有一個根節點
  2. 除根節點外,其它點都有入度,保證了這一定是個連通圖(仔細想就知道了,有入度肯定連着)
  3. 除根節點外,其它點的入度都是1,保證每個點的根節點只有一個(這也保證了圖不可能有環)

所以呢,並查集也可以做這題,操作就是:

  1. 連通分量爲1 (Find(i) == i的數量只有1)
  2. 且圖無環。(在合併操作裏面可以判斷)

當然了,這題有個很的地方----就是沒有點也算樹。
講道理圖不可能是空集,既然出題人覺得 空即是色 的話,那就加個特判吧……

這裏先列出用樹的性質做的代碼。

#include <bits/stdc++.h>///注意poj不能用萬能頭,自行更改吧
using namespace std;
int T,n,a,b;
int e[100005];///入度
int book[100005];///標記這個點是否出現
int main()
{
    int mx=0;///我要遍歷存在的點。。這裏是用數組下標,所以我要保存遍歷到哪裏
    int cnt=1;///這個just是用來輸出的時候看是第幾個例子而已……不用管
    int isp=1;///這就是判斷是不是空集的標記
    while(scanf("%d%d",&a,&b)!=EOF)
    {
        if(a+b<0)break;///-1 -1的時候結束
        if(a==0 && b==0)///兩個都是0的時候判斷
        {
            int ans=0;///入度爲0的個數(有幾個根,很明顯只能有一個根)
            int flag=1;///是否除了根節點以外都是入度爲1的呢?
            for(int i=1;i<=mx;i++)
            {
                if(book[i] && e[i]==0)///判斷出現並且入度爲0,那就是根
                {
                    ans++;
                }
                else if(book[i] && e[i]!=1)///不是根,那就判斷入度是不是1
                {
                    flag=0;
                }
            }
            ///hdu 1272的只有輸出不一樣!(HDU1325)(POJ1308)都是這個板子
            if((flag==1 && ans==1) || isp)printf("Case %d is a tree.\n",cnt);
            else printf("Case %d is not a tree.\n",cnt);
            ///這些都是初始化
            memset(e,0,sizeof(e));
            memset(book,0,sizeof(book));
            mx=0;
            cnt++;
            isp=1;
        }
        else{
            isp=0;
            e[b]++;///入度
            book[a]=1;///標記這個點是否出現
            book[b]=1;
            mx=(max(a,max(mx,b)));
        }
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章