首页 > 技术文章 > 49最小高度树(310)

zmmm 2020-09-08 18:12 原文

作者: Turbo时间限制: 1S章节: DS:图

晚于: 2020-08-05 12:00:00后提交分数乘系数50%

截止日期: 2020-08-12 12:00:00

问题描述 :

对于一个具有树特征的无向图,我们可选择任何一个节点作为根。图因此可以成为树,在所有可能的树中,具有最小高度的树被称为最小高度树。给出这样的一个图,写出一个函数找到所有的最小高度树并返回他们的根节点。

该图包含 n 个节点,标记为 0 到 n - 1。给定数字 n 和一个无向边 edges 列表(每一个边都是一对标签)。

你可以假设没有重复的边会出现在 edges 中。由于所有的边都是无向边, [0, 1]和 [1, 0] 是相同的,因此不会同时出现在 edges 里。

 

示例 1:

输入: n = 4, edges = [[1, 0], [1, 2], [1, 3]]

        0

        |

        1

       / \

      2   3 

输出: [1]

 

示例 2:

输入: n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]]

     0  1  2

      \ | /

        3

        |

        4

        |

        5 

输出: [3, 4]

说明:

 根据树的定义,树是一个无向图,其中任何两个顶点只通过一条路径连接。 换句话说,一个任何没有简单环路的连通图都是一棵树。

树的高度是指根节点和叶子节点之间最长向下路径上边的数量。

 

可使用以下main函数:

int main()

{

    int n;

    vector<vector<int> > edges;

    cin>>n;

    int p1,p2;

    for(int i=0; i<n-1; i++)//边的数目为节点数目减1

    {

        cin>>p1>>p2;

        vector<int> edge;

        edge.push_back(p1);

        edge.push_back(p2);

        edges.push_back(edge);

    }

    vector<int> res=Solution().findMinHeightTrees(n, edges);

    sort(res.begin(), res.end());

    for(int i=0; i<res.size(); i++)

    cout<<res[i]<<" ";

}

 

输入说明 :

首先输入节点的个数n,

然后输入n-1行(n个节点存在n-1条边),每行两个整数a,、b,表示节点a和节点b之间存在一条边,a和b不相同。

n<=10002

 

输出说明 :

对于所有找到的根节点,按照编号从小到大的顺序输出,每个编号后跟一个空格。

输入范例 :

输出范例 :

#include <iostream>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
using namespace std;
class Solution {
public:
    vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) 
    {
        if(n==1)
            return {0};
        vector<int> degree(n);//存放节点度数 
        map<int,vector<int>> M;//存放图的邻接表
        vector<int> ans;
        
        for(int i=0;i<edges.size();i++) 
        {
            int p=edges[i][0];
            int q=edges[i][1];
            degree[p]++;
            degree[q]++;
            M[p].push_back(q);
            M[q].push_back(p);
        }
        
        queue<int>  Q;
        //把叶子节点入栈
        for(int i=0;i<n;i++) 
        {
            if(degree[i]==1)
                Q.push(i);
        }
        //从外向内一层一层剥,每次加入的都是一层的
        while(!Q.empty())
        {
            int len=Q.size();
            ans.clear();
            
            for(int i=0;i<len;i++)
            {
                int temp=Q.front();
                Q.pop();
                ans.push_back(temp);
                degree[temp]--;
                
                for(auto t:M[temp])
                {
                    degree[t]--;
                    if(degree[t]==1)
                        Q.push(t);
                }
            }
        }
        return ans;
    }
};
int main()
{
    int n;
    vector<vector<int> > edges;
    cin>>n;
    int p1,p2;
    for(int i=0; i<n-1; i++)//边的数目为节点数目减1
    {
        cin>>p1>>p2;
        vector<int> edge;
        edge.push_back(p1);
        edge.push_back(p2);
        edges.push_back(edge);
    }
    vector<int> res=Solution().findMinHeightTrees(n, edges);
    sort(res.begin(), res.end());
    for(int i=0; i<res.size(); i++)
    cout<<res[i]<<" ";
}

 

推荐阅读