LintCode 1395: The Barycentre Of The Trees (树的重心-树上的DP题)

  1. The Barycentre Of The Trees

For a multi-branch tree, if there is a node R with R as the root, and the largest sub-tree of all its sub-trees has the least number of nodes, the node R is said to be the center of gravity of the tree.
Now give you a multi-branch tree with n nodes. Find the center of gravity of this tree. If there are multiple centers of gravity, return the one with the lowest number.
x[i], y[i] represents the two points of the i-th edge.

Example
Example 1:

Given x = [1], y = [2], return 1.
Input:
[1]
[2]
Output:
1

Explanation:
Both 1 and 2 can be center of gravity, but the number of 1 is the smallest.
Example 2:

Given x = [1,2,2], y = [2,3,4], return 2.
Input:
[1,2,2]
[2,3,4]
Output:
2

Explanation:
2 is the center of gravity.
Notice
2 <= n <= 10^5
1 <= x[i], y[i] <= n

解法1:
这题是典型的树上的DP题。
思路:

  1. 先把无根树转有根树,建立tree数组,即A-B链接要建立A->B和B->A这两个链接。
  2. dfs()里面要注意对节点x遍历其子节点时,需要考虑子节点不能为x的父节点f,不然陷入死循环。
  3. 因为2)里面我们没有考虑x的父节点f,但实际上因为这是无联通图,x和f是双向链接,所以f也是x的子节点。所以还要考虑以f为节点的子节点数目,其为n - dp[x]。
class Solution {
public:
    /**
     * @param x: The vertexes of the edges
     * @param y: The vertexes of the edges
     * @return: Return the index of barycentre
     */
    int getBarycentre(vector<int> &x, vector<int> &y) {
        if (x.size() == 0) return 0;
        n = x.size() + 1;
        tree.resize(n + 1, vector<int>());  //same as tree.resize(n + 1)
        dp.resize(n + 1); //dp[i] is the the sum of the children nodes under the tree with root i plus 1, dp[i] = sum(dp[j]) + 1;
        
        for (int i = 0; i < x.size(); ++i) {
            tree[x[i]].push_back(y[i]);
            tree[y[i]].push_back(x[i]);
        }
        dfs(1, 0); //choose 1 as the root
        return gChosenNode;
    }
    
private:
    vector<vector<int>> tree;
    vector<int> dp;
    int gMaxSubTreeSize = INT_MAX;
    int gChosenNode = 0;
    int n;
    void dfs(int node, int father) {
        int maxSubTreeSize = 0;
        if (tree[node].size() == 0) {
            dp[node] = 1; //leave node
        } else {
            for (int i = 0; i < tree[node].size(); ++i) {
                int childNode = tree[node][i];
                if ( childNode != father) { // prevent endless loop
                    dfs(childNode, node);
                    dp[node] += dp[childNode];
                    maxSubTreeSize = max(maxSubTreeSize, dp[childNode]);
                }
            }
            dp[node] += 1; // add itself
        }
        maxSubTreeSize = max(maxSubTreeSize, n - dp[node]);
        if (maxSubTreeSize < gMaxSubTreeSize || (maxSubTreeSize == gMaxSubTreeSize && node < gChosenNode)) {
            gMaxSubTreeSize = maxSubTreeSize;
            gChosenNode = node;
        }
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值