leetcode 310 最小高度树(拓扑排序变形)

题目描述:

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

题解:

  首先要确定一个结论,最小高度树最多只有两个。可以用反证法证明,假设有n(n>=3)个最小高度树,那么这三个树的高度要一致。在这三个节点相邻的情况下(不相邻的情况一定不存在,可以推一下),分别取这三个节点为根节点的树的高度不一致,与假设相悖。

  再就是有向图的一个拓扑排序:

  step1:把度为1的点去掉(注意,一次操作需要把所有度为1的点去掉)

  step2:重复step1,直到剩下的节点个数小于等于2

 

AC代码:

  

class Solution {
public:
    // 
    vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
        for(int i=0;i<n;i++)
        {
            edge[i].clear();
            degree[i] = 0;
        }
        int edge_Len = edges.size();
        for(int i=0;i<edge_Len;i++)
        {
            edge[edges[i][0]].push_back(edges[i][1]);
            edge[edges[i][1]].push_back(edges[i][0]);
            degree[edges[i][0]]++;
            degree[edges[i][1]]++;
        }

        vector<int> ans;
        queue<int> que;
        for(int i=0;i<n;i++)
        {
            if(degree[i] == 1 || degree[i] == 0) que.push(i);
        }
        int cnt = n;
        // 剩余节点的个数
        while(cnt>2)
        {
            // 把所有度为1的点都处理掉
            while(!que.empty())
            {
                int now = que.front();
                que.pop();
                cnt--;
                degree[now] = -1;
                int Len  = edge[now].size();
                for(int i=0;i<Len;i++)
                {
                    int next= edge[now][i];
                    degree[next]--;
                }
            }
            for(int i=0;i<n;i++)
            {
                if(degree[i] == 1 || degree[i] == 0) que.push(i);
            }
        }
        while(!que.empty())
        {
            int now = que.front();
            que.pop();
            ans.push_back(now);
        }
        return ans;
    }

private:
    vector<int> edge[10010];
    int degree[10010];
    
}; 

 

posted @ 2020-04-02 20:54  猪突猛进!!!  阅读(193)  评论(0编辑  收藏  举报