PAT(甲)1021 Deepest Root (25)(詳解)

1021 Deepest Root (25)(25 分)

題目描述:

A graph which is connected and acyclic can be considered a tree. The height of the tree depends on the selected root. Now you are supposed to find the root that results in a highest tree. Such a root is called the deepest root.


  • 輸入格式
    Each input file contains one test case. For each case, the first line contains a positive integer N (<=10000) which is the number of nodes, and hence the nodes are numbered from 1 to N. Then N-1 lines follow, each describes an edge by given the two adjacent nodes’ numbers.

  • 輸出格式
    For each test case, print each of the deepest roots in a line. If such a root is not unique, print them in increasing order of their numbers. In case that the given graph is not a tree, print “Error: K components” where K is the number of connected components in the graph.


題目大意:
題目就是要對一個樹形結構,去尋找能夠以某個結點以其爲根,深度最大,如果有多個,則升序輸出。解題思路參考自這裏

解題方法:
採用dfs對圖進行遍歷,因爲如果是連通圖,dfs就能把所有結點都遍歷完,而如果不是連通圖,則需要至少2次以上,因此根據這個特性可以用來判斷是否是樹。同時,通過dfs,可以將最深的葉子結點找出來。這裏需要注意一點,類似於(1-2-3)這樣的樹形結構,1和3都可以被稱爲root結點,因此,我們可以通過對第一遍dfs得到遍歷結果中,隨便取一個,反向dfs,最終把結果全部放入set中,把兩次dfs的並集放入。


程序:

#include <stdio.h>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;

int maxHight = 0;
set <int> s;    /* 保存深度最大的根結點集合(默認升序) */
vector <vector<int> > v;    /* 保存點與點之間的聯繫 */
vector <int> temp;  /* 保存深度最大點的向量 */
bool visit[10001];

void dfs(int node, int height)
{   /* 深度優先搜索遍歷 */
    if (height > maxHight)  /* 如果當前結點的深度比最大深度還要大 */
    {
        maxHight = height;
        temp.clear();
        temp.push_back(node);
    }
    else if (height == maxHight)  /* 如果相同,將相同深度的結點放入temp */
        temp.push_back(node);
    visit[node] = true;     /* 置該點爲已訪問 */
    for (int i = 0; i < v[node].size(); i++)  /* 遍歷v[node]的所有孩子 */
        if (visit[v[node][i]] == false)
            dfs(v[node][i], height+1);
}

int main(int argc, char const *argv[])
{
    int N, father, child, cnt = 0;
    scanf("%d", &N);
    fill(visit, visit+N+1, false);    /* 初始化visit */
    v.resize(N+1);  /* 調整vector的大小 */
    for (int i = 0; i < N-1; i++) /* 輸入父節點和孩子節點之間的聯繫 */
    {   
        scanf("%d %d", &father, &child);
        v[father].push_back(child);
        v[child].push_back(father);
    }
    for (int i = 1; i <= N; i++)    /* 編號從1開始 */
        if (visit[i] == false)  /* 如果還未訪問過 */
        {
            dfs(i, 1);
            if (i == 1)
                for (int j = 0; j < temp.size(); j++)   /* 把當前的葉子結點存入 */
                    s.insert(temp[j]);
            cnt++;  /* 每執行一次cnt++,用於判斷是否是樹 */
        }
    if (cnt >= 2)   /* 如果不是樹 */
        printf("Error: %d components\n", cnt);
    else    /* 從葉子結點出發,去尋找最深的根結點 */
    {
        fill(visit, visit+N+1, false);    /* 重置visit */
        temp.clear();
        maxHight = 0;   
        dfs(temp[0], 1);    /* 因爲樹是連通的,所以從任意一個葉節點出發都能遍歷到所有最深的父節點 */
        for (int j = 0; j < temp.size(); j++)
            s.insert(temp[j]);
        set <int>::iterator it;
        for (it = s.begin(); it != s.end(); it++)
            printf("%d\n", *it);
    }
    return 0;
}

如果對您有幫助,幫忙點個小拇指唄~

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