POJ 1655 Balancing Act (求树的重心)树形DP(经典)
Posted 00isok
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1655 Balancing Act (求树的重心)树形DP(经典)相关的知识,希望对你有一定的参考价值。
<题目链接>
题目大意:
给你一棵树,任意去除某一个点后,树被分成了几个联通块,则该点的平衡值为所有分成的连通块中,点数最大的那个,问你:该树所有点中,平衡值最小的那个点是什么?
解题分析:
运用递归,找到以u为根节点,所有子节点数的最大值,然后求出这些最大值的最小值。
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; const int MAXN = 20010; struct Edge { int to,next; }edge[MAXN*2]; int head[MAXN],tot; void init() { memset(head,-1,sizeof(head)); tot = 0; } void addedge(int u,int v) { edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++; } int dp[MAXN],num[MAXN]; int n; void dfs(int u,int pre) { dp[u] = 0;num[u] = 1; for(int i = head[u];i != -1;i = edge[i].next) { int v = edge[i].to; if(v == pre)continue; //如果下一个点是u的父亲(即刚刚走过的点),那么跳过,防止下一步dfs(v,u)遍历该无向图时,不停的在两个点之间来回遍历 dfs(v,u); //继续从它的子节点开始向下搜索 dp[u] = max(dp[u],num[v]); //dp[u]指的是u的每个子节点方向所对应的最大节点数的最大值 num[u] += num[v]; } //num[u]此时代表除父节点方向外的所有子节点数(包括它本身,,因为num[u]初始化为1) dp[u] = max(dp[u],n - num[u]); //n-num[u]指的是dp[u]父节点方向的节点数 } int main() { int T; scanf("%d",&T); int u,v; while(T--) { scanf("%d",&n); init(); for(int i = 1;i < n;i++) { scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } dfs(1,-1); int ans1 = 1, ans2 = dp[1]; //找到去除该点后,所得连通分量最大点数的最小值,即寻找平衡点 for(int i = 2;i <= n;i++) if(ans2 > dp[i]) { ans1 = i; ans2 = dp[i]; } printf("%d %d ",ans1,ans2); } return 0; }
2018-08-17
以上是关于POJ 1655 Balancing Act (求树的重心)树形DP(经典)的主要内容,如果未能解决你的问题,请参考以下文章