<更新提示>

<第一次更新>


<正文>

树的重心

我们先来认识一下树的重心。

树的重心也叫树的质心。找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡。

根据树的重心的定义,我们可以通过树形DP来求解树的重心。

设\(Max_i\)代表删去i节点后树中剩下子树中节点最多的一个子树的节点数。由于删去节点i至少将原树分为两部分,所以满足\(\ \frac{1}{2}n \leq Max_i\),我们要求的就是一个\(i\),使得\(Max_i\)最小。

对于Max数组,我们可以列出如下状态转移方程:

\[Max_i=\max_{j\in son(i)}\{size_j,n-size_i\}
\]

size数组即为节点个数(树的大小),可以在树形DP中顺带求解。

\(Code:\)

inline void dp(int r,int f)
{
size[r]=1;
for(int i=0;i<Link[r].size();i++)
{
int Son=Link[r][i];
if(Son==f)continue;
dp(Son,r);
size[r]+=size[Son];
Max[r]=max(Max[r],size[Son]);
}
Max[r]=max(Max[r],n-size[r]);
if(Max[r]==Max[ans]&&r<ans)ans=r;
if(Max[r]<Max[ans])ans=r;
}

还是通过一道例题来认识一下。

Balancing Act(POJ1655)

Description

The city consists of intersections and streets that connect them.

Heavy snow covered the city so the mayor Milan gave to the winter-service a list of streets that have to be cleaned of snow. These streets are chosen such that the number of streets is as small as possible but still every two intersections to be connected i.e. between every two intersections there will be exactly one path. The winter service consists of two snow plovers and two drivers, Mirko and Slavko, and their starting position is on one of the intersections.

The snow plover burns one liter of fuel per meter (even if it is driving through a street that has already been cleared of snow) and it has to clean all streets from the list in such order so the total fuel spent is minimal. When all the streets are cleared of snow, the snow plovers are parked on the last intersection they visited. Mirko and Slavko don’t have to finish their plowing on the same intersection.

Write a program that calculates the total amount of fuel that the snow plovers will spend.

Input Format

The first line of the input contains two integers: N and S, 1 <= N <= 100000, 1 <= S <= N. N is the total number of intersections; S is ordinal number of the snow plovers starting intersection. Intersections are marked with numbers 1...N.

Each of the next N-1 lines contains three integers: A, B and C, meaning that intersections A and B are directly connected by a street and that street's length is C meters, 1 <= C <= 1000.

Output Format

Write to the output the minimal amount of fuel needed to clean all streets.

Sample Input

5 2
1 2 1
2 3 2
3 4 2
4 5 1

Sample Output

6

解析

这个就是树的重心的模板题了嘛。

还有题目的第二问就是重心子树中节点数最多的子树的节点数。嗯!刚好符合我们Max数组的定义,直接输出就可以了。

\(Code:\)

#include<cstdio>
#include<iostream>
#include<queue>
#include<vector>
#include<cstring>
#define mset(name,val) memset(name,val,sizeof name)
using namespace std;
const int N=20000+50;
int n,size[N],Max[N],ans,cnt;
vector < int > Link[N];
inline void input(void)
{
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
Link[x].push_back(y);
Link[y].push_back(x);
}
}
inline void dp(int r,int f)
{
size[r]=1;
for(int i=0;i<Link[r].size();i++)
{
int Son=Link[r][i];
if(Son==f)continue;
dp(Son,r);
size[r]+=size[Son];
Max[r]=max(Max[r],size[Son]);
}
Max[r]=max(Max[r],n-size[r]);
if(Max[r]==Max[ans]&&r<ans)ans=r;
if(Max[r]<Max[ans])ans=r;
}
int main(void)
{
int T;
scanf("%d",&T);
while(T--)
{
mset(Max,0x00);
mset(size,0x00);
ans=0;cnt=0;Max[0]=0x3f3f3f3f;
input();
dp(1,0);
printf("%d %d\n",ans,Max[ans]);
for(int i=1;i<=n;i++)
Link[i].clear();
}
}

<后记>

『Balancing Act 树的重心』的更多相关文章

  1. POJ 1655 Balancing Act 树的重心

    Balancing Act   Description Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. ...

  2. POJ1655 Balancing Act(树的重心)

    题目链接 Balancing Act 就是求一棵树的重心,然后统计答案. #include <bits/stdc++.h> using namespace std; #define REP ...

  3. poj-1655 Balancing Act(树的重心+树形dp)

    题目链接: Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11845   Accepted: 4 ...

  4. PKU 1655 Balancing Act(树+树的重心)

    #include<cstdio> #include<cstring> #include<algorithm> #define maxn 20005 using na ...

  5. 『左偏树 Leftist Tree』

    新增一道例题 左偏树 Leftist Tree 这是一个由堆(优先队列)推广而来的神奇数据结构,我们先来了解一下它. 简单的来说,左偏树可以实现一般堆的所有功能,如查询最值,删除堆顶元素,加入新元素等 ...

  6. POJ 1655 - Balancing Act 树型DP

    这题和POJ 3107 - Godfather异曲同工...http://blog.csdn.net/kk303/article/details/9387251 Program: #include&l ...

  7. poj1655 Balancing Act 找树的重心

    http://poj.org/problem? id=1655 Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submis ...

  8. POJ 1655 Balancing Act【树的重心】

    Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14251   Accepted: 6027 De ...

  9. POJ 1655.Balancing Act 树形dp 树的重心

    Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14550   Accepted: 6173 De ...

随机推荐

  1. Tomcat映射路径

    打开tomcat安装包,在config目录下修改server.xml文件: 在<Host>标签中添加: <Context path="" docBase=&quo ...

  2. Linux学习之shell

    通配符 *:表示从它所在位置开始到某个符合条件的结束符之间的任何字符 ?:表示它所在位置上的任何可能的单个字符 []:表示[]中所包含字符的任何一个 特殊键 ctrl+c  #停止当前程序执行 ctr ...

  3. java字符串转json

    针对不同jar包 一: import org.json.JSONObject; JSONObject jo = new JSONObject(new String(需要转换的字符串)); 二: imp ...

  4. 如何简单地理解Python中的if __name__ == '__main__'

    https://blog.csdn.net/yjk13703623757/article/details/77918633 1. 摘要 通俗的理解__name__ == '__main__':假如你叫 ...

  5. springboot增删改查

    改https://blog.csdn.net/weixin_42338186/article/details/81561592 添加https://blog.csdn.net/weixin_42338 ...

  6. 将普通用户添加到sudo

    将普通用户添加到sudo组 可以编辑/etc/sudoers文件将普通用户加入sudo组.要注意的是修改该文件只能使用visudo命令:1.首先切换到root #su - (注意有 “-” ,这和su ...

  7. Linux结束进程到底有多少种方法?

    我们经常在Linux里使用kill命令来结束某后台进程.但kill命令实际上是向进程发送信号,并且有多种信号.终止运行一个程序只是其中一个信号而已.kill是根据进程号发送信号的,而另一个工具kill ...

  8. vue的父子组建之间的通信(-),基于props和$emit之间的传递

    对于vue而言,以为其核心思想为前端组建化.所以组建之间的通信必不可少. 相信接触过Angularjs的童鞋都知道angularjs的控制器之间的通信机制. 1:父传子:官方的$broadcast() ...

  9. 《SpringMVC从入门到放肆》八、SpringMVC注解式开发(基本配置)

    上一篇我们结束了配置式开发,配置式开发目前在企业中用的并不是很多,大部分企业都在使用注解式开发,所以今天我们就来学习注解式开发.所谓SpringMVC注解式开发是指,处理器是基于注解的类的开发方式.对 ...

  10. centos7防火墙配置

    一.在工作中远程连接经常通过堡垒机连接,不能直接开启防火墙.所以就需要写入配置文件中 编译配置文件   /etc/firewalld/zones/public.xml <?xml version ...