[BZOJ3391][Usaco2004 Dec]Tree Cutting网络破坏

Description

    约翰意识到贝茜建设网络花费了他巨额的经费,就把她解雇了.贝茜很愤怒,打算狠狠报
复.她打算破坏刚建成的约翰的网络.    约翰的网络是树形的,连接着N(1≤N≤10000)个牛棚.她打算切断某一个牛棚的电源,使和这个牛棚相连的所有电缆全部中断.之后,就会存在若干子网络.为保证破坏够大,每一个子网的牛棚数不得超过总牛棚数的一半,那哪些牛棚值得破坏呢?

Input

    第1行:一个整数N.
    第2到N+1行:每行输入两个整数,表示一条电缆的两个端点.

Output

    按从小到大的顺序,输出所有值得破坏的牛棚.如果没有一个值得破坏,就输出“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

如果牛棚3或牛棚8被破坏,剩下的三个子网节点数将是5,2,2,没有超过5的.


如果是树的话比较好处理...

直接dfs找就行了。

如果不是树...

不会233


// By BriMon
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
inline int read(){
    int res=0;char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)){res=(res<<3)+(res<<1)+(ch^48);ch=getchar();}
    return res;
}
#define N 10005
int n;
struct edge{
    int nxt, to;
}ed[N*2];
int head[N], cnt;
inline void add(int x, int y)
{
    ed[++cnt] = (edge){head[x], y};
    head[x] = cnt;
}
bool ok[N];
int siz[N];

void dfs(int x, int fa)
{
    siz[x] = 1;
    for (int i = head[x] ; i ; i = ed[i].nxt)
    {
        int to = ed[i].to;
        if (fa != to) 
        {
            dfs(to, x);
            siz[x] += siz[to];
            if (siz[to] > n / 2) ok[x] = false;
        }
    }
    if (n - siz[x] > n / 2) ok[x] = false;
}

int main()
{
    n = read();
    for (int i = 1 ; i < n ; i ++)
    {
        int x = read(), y = read();
        add(x, y), add(y, x);
    }
    for (int i = 1 ; i <= n ; i ++) ok[i] = true;
    dfs(1, 0);
    bool flag = 0;
    for (int x = 1 ; x <= n ; x ++)
        if (ok[x]) printf("%d
", x), flag = 1;
    if (!flag) puts("NONE");
    return 0;
}
原文地址:https://www.cnblogs.com/BriMon/p/9418609.html