poj 2378 Tree Cutting (树形dp)

Tree Cutting

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3910   Accepted: 2347

Description

After Farmer John realized that Bessie had installed a "tree-shaped" network among his N (1 <= N <= 10,000) barns at an incredible cost, he sued Bessie to mitigate his losses.

Bessie, feeling vindictive, decided to sabotage Farmer John‘s network by cutting power to one of the barns (thereby disrupting all the connections involving that barn). When Bessie does this, it breaks the network into smaller pieces, each of which retains
full connectivity within itself. In order to be as disruptive as possible, Bessie wants to make sure that each of these pieces connects together no more than half the barns on FJ.

Please help Bessie determine all of the barns that would be suitable to disconnect.

Input

* Line 1: A single integer, N. The barns are numbered 1..N.

* Lines 2..N: Each line contains two integers X and Y and represents a connection between barns X and Y.

Output

* Lines 1..?: Each line contains a single integer, the number (from 1..N) of a barn whose removal splits the network into pieces each having at most half the original number of barns. Output the barns in increasing numerical order. If there are no suitable
barns, the output should be a single line containing the word "NONE".

Sample Input

10
1 2
2 3
3 4
4 5
6 7
7 8
8 9
9 10
3 8

Sample Output

3
8

Hint

INPUT DETAILS:

The set of connections in the input describes a "tree": it connects all the barns together and contains no cycles.

OUTPUT DETAILS:

If barn 3 or barn 8 is removed, then the remaining network will have one piece consisting of 5 barns and two pieces containing 2 barns. If any other barn is removed then at least one of the remaining pieces has size at least 6 (which is more than half of the
original number of barns, 5).

Source

类似于poj3107

求删除一个点后,形成的森林中,每棵树中最大节点数不大于原树节点数目的一半。

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define ll long long
#define N 11000
#define mem(a,t) memset(a,t,sizeof(a))
const int inf=1000005;
int cnt,n;
struct node
{
    int v,next;
}e[N*2];
int head[N];
int num[N];
int ans[N];
int n1;
void add(int u,int v)
{
    e[cnt].v=v;
    e[cnt].next=head[u];
    head[u]=cnt++;
}

void dfs(int u,int len,int fa)
{
    int i,v,sum=0,tmp=0;
    num[u]=1;
    for(i=head[u];i!=-1;i=e[i].next)
    {
        v=e[i].v;
        if(v!=fa)
        {
            dfs(v,len+1,u);
            tmp=max(tmp,num[v]);
            num[u]+=num[v];
        }
    }

    int t=max(tmp,n-num[u]);
    if(t<=n/2)
        ans[n1++]=u;
}

int main()
{
    //freopen("in.txt","r",stdin);
    int i,u,v;
    while(~scanf("%d",&n))
    {
        cnt=0;
        mem(head,-1);
        for(i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
        }
        mem(num,0);
        n1=0;
        dfs(1,0,-1);
        sort(ans,ans+n1);
        for(i=0;i<n1;i++)
            printf("%d\n",ans[i]);
    }
    return 0;
}
时间: 2024-10-13 19:32:10

poj 2378 Tree Cutting (树形dp)的相关文章

POJ 2378 Tree Cutting(树的重心)

题目链接:http://poj.org/problem?id=2378 题目: Description After Farmer John realized that Bessie had installed a "tree-shaped" network among his N (1 <= N <= 10,000) barns at an incredible cost, he sued Bessie to mitigate his losses. Bessie, fee

POJ 2378 Tree Cutting (DFS)

题目链接:http://poj.org/problem?id=2378 一棵树,去掉一个点剩下的每棵子树节点数不超过n/2.问有哪些这样的点,并按照顺序输出. dfs回溯即可. 1 //#pragma comment(linker, "/STACK:102400000, 102400000") 2 #include <algorithm> 3 #include <iostream> 4 #include <cstdlib> 5 #include &l

POJ 2378 Tree Cutting (树的重心,微变形)

题意: 给定一棵树,n个节点,若删除点v使得剩下的连通快最大都不超过n/2,则称这样的点满足要求.求所有这样的点,若没有这样的点,输出NONE. 思路: 只需要拿“求树的重心”的代码改一行就OK了.因为依然是在判别最大连通块的点数. 1 //#include <bits/stdc++.h> 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath&g

POJ 2378 Tree Cutting 子树统计

题目大意:给出一棵树,将树中的一个节点去掉之后,这棵树会分裂成一些联通块,求去掉哪些点之后,所有联通块的大小不超过所有节点的一半,并按顺序输出. 思路:基础的子树统计问题,只要深搜一遍就可以出解.这个步骤和求树的重心很像,是树分治的基础. CODE: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 10010 using nam

hdu5593--ZYB&#39;s Tree(树形dp)

问题描述 ZYB有一颗N个节点的树,现在他希望你对于每一个点,求出离每个点距离不超过KK的点的个数. 两个点(x,y)在树上的距离定义为两个点树上最短路径经过的边数, 为了节约读入和输出的时间,我们采用如下方式进行读入输出: 读入:读入两个数A,B,令fai??为节点i的父亲,fa?1??=0;fa?i??=(A∗i+B)%(i−1)+1,i∈[2,N] . 输出:输出时只需输出N个点的答案的xor和即可. 输入描述 第一行一个整数TT表示数据组数. 接下来每组数据: 一行四个正整数N,K,A,

codeforces 161D - Distance in Tree(树形dp)

题目大意: 求出树上距离为k的点对有多少个. 思路分析: dp[i][j] 表示 i 的子树中和 i 的距离为 j 的点数有多少个.注意dp[i] [0] 永远是1的. 然后在处理完一颗子树后,就把自身的dp 更新. 更新之前更新答案. 如果这颗子树到 i 有 x 个距离为j的.那么答案就要加上 dp[i] [ k-j-1] * x; #include <iostream> #include <cstdio> #include <cstring> #include &l

poj 2324 Anniversary party(树形DP)

/*poj 2324 Anniversary party(树形DP) ---用dp[i][1]表示以i为根的子树节点i要去的最大欢乐值,用dp[i][0]表示以i为根节点的子树i不去时的最大欢乐值, ---于是当i去时,i的所有儿子都不能去:dp[i][1]=sum(dp[j][0])+a[i],其中j是i的儿子节点. ---当i不去时,i的儿子可去也可不去:dp[i][0]=sum(max(dp[j][0],dp[j][1])),j是i的儿子节点 ---边界条件:当i时叶子节点时,dp[i][

POJ 2486 Apple Tree (树形DP,树形背包)

题意:给定一棵树图,一个人从点s出发,只能走K步,每个点都有一定数量的苹果,要求收集尽量多的苹果,输出最多苹果数. 思路: 既然是树,而且有限制k步,那么树形DP正好. 考虑1个点的情况:(1)可能在本子树结束第k步(2)可能经过了j步之后,又回到本节点(第k步不在本子树) 第二种比较简单,背包一下,就是枚举给本节点的孩子t多少步,收集到最多苹果数.第一种的话要求第k步终止于本节点下的某个子树中,那么只能在1个孩子子树中,所以应该是[其他孩子全部得走回来]+[本孩子不要求走回来]   or  

POJ 1947 Rebuilding Roads (树形dp 经典题)

Rebuilding Roads Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 9499   Accepted: 4317 Description The cows have reconstructed Farmer John's farm, with its N barns (1 <= N <= 150, number 1..N) after the terrible earthquake last May. The