cogs 1143. [石门中学2009] 切割树

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

 

posted @ 2017-09-09 10:27  一蓑烟雨任生平  阅读(106)  评论(0编辑  收藏  举报