• POJ 1655 Balancing Act (树形DP求树的重心)


    题意:

    求一棵树中以某个点为重心最小的子树集, 就是去掉这个点, 图中节点最多的联通块节点最少。

    分析:

    想知道这个点是不是最优的点, 只要比较它子树的数量和除去这部分其他的数量(它的父节点那部分树), 最后循环一遍找最优即可。

    #include<stdio.h>
    #include<vector>
    #include<algorithm>
    #include<string.h>
    #include<iostream>
    using namespace std;
    
    const int maxn = 25000 + 7;
    const int inf = 1e9 + 7;
    int Max[maxn];//记录以该节点为重心,子树节点的最大值
    int Num[maxn];//记录包括该节点不回溯到父亲节点有多少个子节点
    vector<int> G[maxn];
    int N;
    void init() {
        for(int i = 0; i < maxn; i ++) {
            G[i].clear();
        }
    }
    void dpMax(int u, int pre) {
    
        Num[u] = 1, Max[u] = 0;
    
        for(int i = 0; i < G[u].size(); i++) {
            int v = G[u][i];
            if(v == pre)
                continue;
            dpMax(v, u);
            Max[u] = max(Max[u], Num[v]);
            Num[u] += Num[v];
        }
        Max[u] = max(Max[u], N - Num[u]);//比较一下自己子树和父亲子树的最大值
    
    }
    int main() {
        int T;
        cin >> T;
        while(T--) {
            init();
            cin >> N;
            for(int i = 0; i < N - 1; i++) {
                int u, v;
                cin >> u >> v;
                G[u].push_back(v);
                G[v].push_back(u);
            }
    //        Max[0] = inf;
            dpMax(1, -1);
            int ansNum = inf, ansInd = 1;
            for(int i = 1; i <= N; i++){
                if(ansNum > Max[i]){
                    ansNum = Max[i];
                    ansInd = i;
                }
            }
            cout << ansInd << " " << ansNum << "
    ";
        }
        return 0;
    }
  • 相关阅读:
    HDOJ_ACM_超级楼梯
    HDOJ_ACM_下沙的沙子有几粒?
    杭电_ACM_How Many Trees
    HDOJ_ACM_Tiling_easy version
    HDOJ_ACM_母牛的故事
    HDOJ_ACM_小兔的棋盘
    HDOJ_ACM_一只小蜜蜂
    杭电_ACM_Count the Trees
    HDOJ_ACM_折线分割平面
    Sun Solaris下JAVA以及JSP开发环境的配制小记
  • 原文地址:https://www.cnblogs.com/Jadon97/p/9155615.html
Copyright © 2020-2023  润新知