POJ-2378-Tree Cutting (tree DP)

Tree Cutting

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

Problem-solving ideas:

Compared to the previous blog topic HDU-2196 (DP classic problem tree) Portal . Easier.
Weights are no longer right side, but the number of points on the path.
Title mean to a tree. Demand which points to delete (delete means delete all point one point and this point is attached to the side), the total number of points the rest of the class tree x is not greater than n / 2.
So when solved, or the same routine, twice DFS.
DFS seeking a first pass of each sub-tree for each point and the number of nodes. Re-recorded a total number of nodes and. Way mark at this point there is no possibility deleted. If there is a subtree points greater than n / 2 then it certainly is not deleted.
DFS second time solving the answer. The total number of nodes including a parent node comprising a third parameter is passed down one level. You can prune. If this time has been more than n / 2 down so there is no need because the further down are definitely exceeded. When the transmission parameters down, put on a layer parameters plus all of the sub-tree node by subtracting the number of points the current traversal subtree plus one (because he himself is a point).

AC Code:

//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <math.h>
#include <algorithm>
#include <map>
#include <queue>
#include <deque>
#define ios std::ios::sync_with_stdio(false)
#define int long long
using namespace std;
const int N = 3e5+10;
struct node{
    int val;	// 子树点数总和
    int flag;	// 有没有可能删掉
    vector<int> to;	 // 子树
    vector<int> wei; // 各个子树的点数和
}nodes[N];
int dp[N];
int n;

int dfs(int pos,int pre)
{
    int res = 0;
    nodes[pos].flag = 1;
    for(int i = 0 ; i < nodes[pos].to.size() ; i ++)
    {
        if(nodes[pos].to[i] == pre) continue;
        int tmp = dfs(nodes[pos].to[i],pos);
        nodes[pos].wei.push_back(tmp);
        res += tmp;
        if(tmp > n/2)  nodes[pos].flag = 0;
    }
    nodes[pos].val = res;
    return res + 1;
}


void dfs2(int pos,int pre,int sum)
{
    //cout<<pos<<" "<<sum<<" "<<nodes[pos].val<<endl;
    if(sum > n/2) return;
    int index = 0;
    for(int i = 0 ; i < nodes[pos].to.size() ; i ++)
    {
        if(nodes[pos].to[i] == pre) continue;
        dfs2(nodes[pos].to[i],pos,sum+1+nodes[pos].val-nodes[pos].wei[index]);
        index ++;
    }
    if(nodes[pos].flag)
        dp[pos] = 1;
}

signed  main()
{

    cin>>n;
    for(int i = 1; i < n ; i  ++)
    {
        int a,b;
        cin>>a>>b;
        nodes[a].to.push_back(b);
        nodes[b].to.push_back(a);
    }
    dfs(1,0);
    dfs2(1,0,0);
    int flag = 1;
    for(int i = 1; i <= n ; i ++)
    {
        if(dp[i])
        {
            flag = 0;
            cout<<i<<endl;
        }
    }
    if(flag)  cout<<"NONE"<<endl; // 写的时候忘记这行代码居然过了。 说明就没有不成立的数据
    return 0;
}

Published 104 original articles · won praise 7 · views 4046

Guess you like

Origin blog.csdn.net/qq_43461168/article/details/104211136