POJ-2378-木カット(木DP)

合わせぎり

ファーマージョンはベッシーは信じられないほどのコストで彼のN(1 <= N <= 10,000)納屋の中で、「ツリー型」のネットワークをインストールしていたことに気づいた後、彼は彼の損失を軽減するために、ベッシーを訴えました。

ベッシー、(それによってその納屋を含むすべての接続を中断する)納屋の1に電源を切断することにより、ファーマージョンのネットワークを妨害することを決めた感じ執念深いです、。ベッシーがこれを行う場合には、それ自体の中に完全な接続を保持し、それぞれが小さな部分、にネットワークを分割します。可能な限り破壊的となるためには、ベッシーは、これらの部分のそれぞれが、FJに一緒に半分以下の納屋を接続していることを確認するために望んでいます。

ヘルプベッシーは、切断に適しているであろう納屋のすべてを決定してください。

入力

  • 1行目:単一の整数は、Nです。納屋は1 ... Nの番号が付けられています。

  • ライン2 ... N:各行は、2つの整数XおよびYを含み、納屋XとYとの間の接続を表します

出力

  • 行1 ...?:各行は、単一の整数(1から... N)番号が含ま除去納屋のほとんど半分の元の数で有する片それぞれにネットワークを分割納屋します。出力数値の昇順で納屋。もし適切な納屋がない場合、出力は単語「NONE」を含む単一の行でなければなりません。

サンプル入力


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

サンプル出力


3
8

問題解決のアイデア:

前回のブログのトピックに比べHDU-2196(DP古典的な問題の木)ポータルより簡単。
重みは、もはや右側ありませんが、パス上のポイントの数。
ツリーへのタイトルの平均。削除するポイント要求(削除手段は、すべての点を一点を削除して、この点は、側に取り付けられている)、ポイントの合計数は、クラスツリーXの残りがn / 2以下です。
だから、解決、または同じルーチン、二回DFSとき。
DFSは、各点の各サブツリーの第1のパス及びノード数を求めます。ノードの総数を再記録し。ウェイマークは、この時点で削除された可能性はありません。2 / nより大きいサブツリーポイントがある場合、それは確かに削除されません。
DFS二度目の回答を解きます。三番目のパラメータを含む親ノードを含むノードの総数は1レベル下渡されます。あなたはプルーニングすることができます。今回は以上のn / 2ダウンしている場合は、さらにダウンを確実に超えているので、その必要はありません。場合下り送信パラメータ、(彼自身がポイントであるため)現在のトラバーサルサブツリープラスワンポイントの数を減算することにより層パラメータプラスサブツリー・ノードのすべての上に置きます。

ACコード:

//#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;
}

公開された104元の記事 ウォン称賛7 ビュー4046

おすすめ

転載: blog.csdn.net/qq_43461168/article/details/104211136