POJ 1655 Balancing Act(简单树型dp)

来源:互联网 发布:初中编程学哪个 编辑:程序博客网 时间:2024/06/05 19:50

题目链接:
POJ 1655 Balancing Act
题意:
给一个n个结点和n1条无向边的树,定义树中每个结点的平衡值是删掉这个结点形成若干子树的所有子树结点数量最大值。
求所有结点中平衡值的最小值。
数据范围:n2104
分析:
比较简单的树型dp。
对每个节点记录以它为根的子树的结点数量,dfs更新即可,再判断下父亲结点之上的结点数量,根节点特判下就好了。
时间复杂度:O(n+m)

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <algorithm>#include <climits>#include <cmath>#include <ctime>#include <cassert>#define IOS ios_base::sync_with_stdio(0); cin.tie(0);using namespace std;typedef long long ll;const int MAX_N = 20010;int T, n, total;int head[MAX_N], num[MAX_N], ans[MAX_N];struct Edge {    int v, next;} edge[MAX_N * 2];void AddEdge(int u, int v){    edge[total].v = v;    edge[total].next = head[u];    head[u] = total++;}void dfs(int u, int p){    for (int i = head[u]; i != -1; i = edge[i].next) {        int v = edge[i].v;        if (v == p) continue;        dfs(v, u);        num[u] += num[v];        ans[u] = max(ans[u], num[v]);    }    num[u]++; // 自身还有一个结点    if (u != 1) ans[u] = max(ans[u], n - num[u]);    //printf("num[%d] = %d ans[%d] = %d\n", u, num[u], u, ans[u]);}void wyr(){    memset(ans, 0, sizeof(ans));    memset(num, 0, sizeof(num));    dfs(1, -1);    int Min = INT_MAX, id = 0;    for (int i = 1; i <= n; ++i) {        if (ans[i] < Min) {            Min = ans[i];            id = i;        }    }    printf("%d %d\n", id, Min);}int main(){    scanf("%d", &T);    while (T--) {        memset(head, -1, sizeof(head));        total = 0;        scanf("%d", &n);        for (int i = 1; i < n; ++i) {            int u, v;            scanf("%d%d", &u, &v);            AddEdge(u, v);            AddEdge(v, u);        }        wyr();    }    return 0;}
0 0
原创粉丝点击