树形DP求树的重心 --SGU 134
2024-10-20 07:37:40
令一个点的属性值为:去除这个点以及与这个点相连的所有边后得到的连通分量的节点数的最大值。
则树的重心定义为:一个点,这个点的属性值在所有点中是最小的。
SGU 134 即要找出所有的重心,并且找出重心的属性值。
考虑用树形DP。
dp[u]表示割去u点,得到的连通分支的节点数的最大值。
tot[u]记录以u为根的这棵子树的节点数总和(包括根)。
则用一次dfs即可预处理出这两个数组。再枚举每个点,每个点的属性值其实为max(dp[u],n-tot[u]),因为有可能最大的连通分支在u的父亲及以上。然后记录答案就可以了。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std; vector<int> G[];
int dp[],tot[];
vector<int> ans; void dfs(int u)
{
tot[u] = ;
for(int i=;i<G[u].size();i++)
{
int v = G[u][i];
if(tot[v] == -)
dfs(v);
else
continue;
dp[u] = max(dp[u],tot[v]);
tot[u] += tot[v];
}
} int main()
{
int n,i,j,u,v;
scanf("%d",&n);
for(i=;i<=n;i++)
G[i].clear();
for(i=;i<n-;i++)
{
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
memset(dp,,sizeof(dp));
memset(tot,-,sizeof(tot));
dfs();
int mini = Mod;
for(i=;i<=n;i++)
{
int tmp = max(dp[i],n-tot[i]);
if(tmp < mini)
{
ans.clear();
ans.push_back(i);
mini = tmp;
}
else if(tmp == mini)
ans.push_back(i);
}
printf("%d %d\n",mini,ans.size());
sort(ans.begin(),ans.end());
printf("%d",ans[]);
for(i=;i<ans.size();i++)
printf(" %d",ans[i]);
puts("");
return ;
}
最新文章
- x:Array的使用
- sql附加数据库错误5120
- :判断101-200之间有多少个素数,并输出所有素数。 程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除, 则表明此数不是素数,反之是素数。
- 【Java】Java处理double相加的结果异常
- 也谈http中get和post
- Android(java)学习笔记129:Tab标签的使用
- table tr分离并加圆角和阴影
- net中使用ETW事件
- request.getparameter和 request.getattribute的差别
- mvc4项目数据库优先的尝试
- (15)IO流之File
- 基于Jmeter的自动化测试实施方案设计
- 查找git ignore的追踪
- UVA - 11235:Frequent values
- 干货 | 揭秘如何增加listing多个类目节点
- mybatis:递归查询,关联查询传入多个参数
- vsftpd中配置文件详解
- 【Linux】深入理解Linux中内存管理
- delphi CopyFileProgressBar 拷贝文件显示进度条
- C#中的事件(event)处理机制