(poj3107Godfather,树形dp,next数组)树的重心

Description

Last years Chicago was full of gangster fights and strange murders. The chief of the police got really tired of all these crimes, and decided to arrest the mafia leaders.

Unfortunately, the structure of Chicago mafia is rather complicated. There are n persons known to be related to mafia. The police have traced their activity for some time, and know that some of them are communicating with each other. Based on the data collected, the chief of the police suggests that the mafia hierarchy can be represented as a tree. The head of the mafia, Godfather, is the root of the tree, and if some person is represented by a node in the tree, its direct subordinates are represented by the children of that node. For the purpose of conspiracy the gangsters only communicate with their direct subordinates and their direct master.

Unfortunately, though the police know gangsters’ communications, they do not know who is a master in any pair of communicating persons. Thus they only have an undirected tree of communications, and do not know who Godfather is.

Based on the idea that Godfather wants to have the most possible control over mafia, the chief of the police has made a suggestion that Godfather is such a person that after deleting it from the communications tree the size of the largest remaining connected component is as small as possible. Help the police to find all potential Godfathers and they will arrest them.

Input

The first line of the input file contains n — the number of persons suspected to belong to mafia (2 ≤ n ≤ 50 000). Let them be numbered from 1 to n.

The following n ? 1 lines contain two integer numbers each. The pair ai, bi means that the gangster ai has communicated with the gangster bi. It is guaranteed that the gangsters’ communications form a tree.

Output

Print the numbers of all persons that are suspected to be Godfather. The numbers must be printed in the increasing order, separated by spaces.

Sample Input

6

1 2

2 3

2 5

3 4

3 6

Sample Output

2 3

Source

Northeastern Europe 2005, Northern Subregion

题目大意:给定一颗有n个节点的树,求出这棵树的所有重心,并按编号从大到小输出。

先给出树的重心的定义:一棵树的重心是指删除这个节点之后使树分成几个部分,使得这几个部分中节点个数的最大值最小。

其实求法非常简单

用son[i]表示节点i的子节点有多少个。

blance表示以节点i为父亲的子树中节点个数的最大值。

那么删除节点i之后形成的几个部分中节点个数的最大值为

max(blance,n-son[i]-1);

然后我们dfs一遍就好了。

注意用vector会超时。需要使用next数组。。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int N=50010;
const int inf=2100000000LL;
struct use{
    int st,en;
}b[1000001];
int son[N],n,ans[N],minn,next[5000001]={0},point[100001]={0},tot;
bool f[N];
void add(int x,int y)
{
    tot++;next[tot]=point[x];point[x]=tot;
    b[tot].st=x;b[tot].en=y;
}
void dfs(int x)
{
    int i,j,u,balance=0;
    son[x]=0;
    f[x]=false;
    for(i=point[x];i;i=next[i]){
        u=b[i].en;
        if(!f[u]) continue;
        dfs(u);
        son[x]+=son[u]+1;
        balance=max(balance,son[u]+1);
    }
    balance=max(balance,n-son[x]-1);
    if(balance<minn){
        minn=balance;
        ans[0]=1;
        ans[1]=x;
    }
    else if(balance==minn){
        ans[0]+=1;
        ans[ans[0]]=x;
    }
}
int main()
{
    int i,j,x,y;
    scanf("%d",&n);
    minn=inf;
    memset(f,1,sizeof(f));
    for(i=1;i<n;++i){
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs(1);
    sort(ans+1,ans+ans[0]+1);
    for(i=1;i<=ans[0];++i)
      printf("%d ",ans[i]);
    printf("\n");
}
时间: 2024-10-11 14:36:23

(poj3107Godfather,树形dp,next数组)树的重心的相关文章

poj 1655 树形dp求取树的重心

http://poj.org/problem?id=1655 Description Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or more trees. Define the balance of a node to be the size of the large

树形DP初步-真树1662

树形DP初步-真树 时间限制: 1000 ms 内存限制: 65536 kb 总通过人数: 119 总提交人数: 123 题目描述 新年到了,白兔家族要搞大大的聚会.但是并不是每只白兔都是同一辈分的,于是便有一棵以老白兔为根的家族树. 每只白兔都有它们自己唯一的整数编号(范围在1到N之间),并且对应一个参加聚会所得的开心值.为了使每个参加聚会的白兔都巨开心,老白兔想让每只白兔和他的上一代白兔不会同时参加聚会. 求参加聚会的白兔获得的最大总开心值. 输入 输入的第一行是一个整数N,1<= N <

POJ3107Godfather[树形DP 树的重心]

Godfather Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6121   Accepted: 2164 Description Last years Chicago was full of gangster fights and strange murders. The chief of the police got really tired of all these crimes, and decided to

HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形dp, 对于每条链u,v,w,我们只在lca(u,v)的顶点上处理它 让dp[i]表示以i为根的指数的最大值,sum[i]表示dp[vi]的和(vi为i的儿子们) 则i点有两种决策,一种是不选以i为lca的链,则dp[i]=sum[i]. 另一种是选一条以i为lca的链,那么有转移方程:dp[i]=

NOIP2011pj表达式的值[树形DP 笛卡尔树]

题目描述 对于1 位二进制变量定义两种运算: 运算的优先级是: 先计算括号内的,再计算括号外的. “× ”运算优先于“⊕”运算,即计算表达式时,先计算× 运算,再计算⊕运算.例如:计算表达式A⊕B × C时,先计算 B × C,其结果再与 A 做⊕运算. 现给定一个未完成的表达式,例如+(*_),请你在横线处填入数字0 或者1 ,请问有多少种填法可以使得表达式的值为0 . 输入输出格式 输入格式: 输入文件名为exp.in ,共 2 行. 第1 行为一个整数 L,表示给定的表达式中除去横线外的运

POJ 3123 Ticket to Ride 状压dp+树形dp 斯坦纳树

题目链接:点击打开链接 题意: 给定n个城市和m条可选择修建的道路 下面n行给出每个城市的名字 下面m行给出每条道路及修建该道路的花费. 下面4行,每行给出一对城市. 目标:使得最后4行的每对城市连通(不同对之间可以不连通)所需要修建的最小花费. 数据保证存在可行解 思路: 首先如果这个问题问的是所有城市都连通,就是一个最小生成树的问题. 这里就相当于多个最小生成树的 问题. 当然图里我们只关心最后的4行8个点,所以我们状压这8个点. 设dp[i][j] 表示以i为根 ,j为8个点中是否在 i

树形DP+(分组背包||二叉树,一般树,森林之间的转换)codevs 1378 选课

codevs 1378 选课 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 学校实行学分制.每门的必修课都有固定的学分,同时还必须获得相应的选修课程学分.学校开设了N(N<300)门的选修课程,每个学生可选课程的数量M是给定的.学生选修了这M门课并考核通过就能获得相应的学分. 在选修课程中,有些课程可以直接选修,有些课程需要一定的基础知识,必须在选了其它的一些课程的基础上才能选修.例如<Frontpage>必须在

『Balancing Act 树的重心』

树的重心 我们先来认识一下树的重心. 树的重心也叫树的质心.找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡. 根据树的重心的定义,我们可以通过树形DP来求解树的重心. 设\(Max_i\)代表删去i节点后树中剩下子树中节点最多的一个子树的节点数.由于删去节点i至少将原树分为两部分,所以满足\(\ \frac{1}{2} \leq Max_i\),我们要求的就是一个\(i\),使得\(Max_i\)最小. 对于Max数组,我们可以列出

树形DP求树的重心 --SGU 134

令一个点的属性值为:去除这个点以及与这个点相连的所有边后得到的连通分量的节点数的最大值. 则树的重心定义为:一个点,这个点的属性值在所有点中是最小的. SGU 134 即要找出所有的重心,并且找出重心的属性值. 考虑用树形DP. dp[u]表示割去u点,得到的连通分支的节点数的最大值. tot[u]记录以u为根的这棵子树的节点数总和(包括根). 则用一次dfs即可预处理出这两个数组.再枚举每个点,每个点的属性值其实为max(dp[u],n-tot[u]),因为有可能最大的连通分支在u的父亲及以上