1. 程式人生 > >cogs 1143. [石門中學2009] 切割樹

cogs 1143. [石門中學2009] 切割樹

wid pan ipa one ring table div sub ++

1143. [石門中學2009] 切割樹

★ 輸入文件:treecut.in 輸出文件:treecut.out 簡單對比
時間限制:1 s 內存限制:128 MB

treecut

題目描述:

有一個N個節點的無根樹,各節點編號為1..N,現在要求你刪除其中的一個點,使分割開的連通塊中節點個數都不超過原來的一半多。

數據範圍

1 <= N <= 10,000

輸入文件 treecut.in

第一行:一個整數N。

後面有N-1行:每行兩個整數 X 和 Y,表示一個邊連接的兩個節點號。

輸出文件 treecut.out

輸出所有可能選擇的點。如果有多個節點,按編號從小到大輸出,每個一行。 如果找不到這樣的點,輸出一行:"NONE".

樣例

輸入

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

樣例說明:

刪除3號或8號

節點,則分枝

最多有5個節點

輸出

3
8

思路:dfs一邊,然後枚舉每個點作為切割點。

#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define
MAXN 10001 using namespace std; vector<int>vec[MAXN]; int n,S,tot; int dad[MAXN],size[MAXN]; void dfs(int now){ size[now]=1; for(int i=0;i<vec[now].size();i++) if(dad[now]!=vec[now][i]){ dad[vec[now][i]]=now; dfs(vec[now][i]); size[now]
+=size[vec[now][i]]; } } bool judge(int now){ if(size[1]-size[now]>S) return false; for(int i=0;i<vec[now].size();i++) if(dad[now]!=vec[now][i]){ int to=vec[now][i]; if(size[to]>S) return false; } return true; } int main(){ freopen("treecut.in","r",stdin); freopen("treecut.out","w",stdout); scanf("%d",&n); S=n/2; for(int i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); vec[u].push_back(v); vec[v].push_back(u); } dfs(1); for(int i=1;i<=n;i++) if(judge(i)) cout<<i<<endl; }

cogs 1143. [石門中學2009] 切割樹