zoukankan      html  css  js  c++  java
  • [DFS]JZOJ 1301 treecut

    Description

      有一个N个节点的无根树,各节点编号为1..N,现在要求你删除其中的一个点,使分割开的连通块中节点个数都不超过原来的一半多。
     

    Input

      第一行:一个整数N (1 <= N <= 10,000)。   后面有N-1行:每行两个整数 X 和 Y,表示一个边连接的两个节点号。

    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
     

    Data Constraint

     
     

    Hint

    样例说明:   删除3号或8号节点,则分枝最多有5个节点

    分析

    很容易想到类似于树的重心的东西,只要这个点所有子树大小不超过一半即可

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N=1e4+10;
    struct Graph {
        int v,nx;
    }g[2*N];
    int cnt,list[N],sz[N],ans[N];
    int n;
    
    void Add(int u,int v) {
        g[++cnt]=(Graph){v,list[u]};list[u]=cnt;
        g[++cnt]=(Graph){u,list[v]};list[v]=cnt;
    }
    
    void DFS(int u,int fa) {
        bool b=1;
        sz[u]=1;
        for (int i=list[u];i;i=g[i].nx)
            if (g[i].v!=fa) {
                DFS(g[i].v,u);
                sz[u]+=sz[g[i].v];
                if (sz[g[i].v]>n/2) b=0;
            }
        if (n-sz[u]<=n/2&&b) ans[++cnt]=u;
    }
    
    int main() {
        scanf("%d",&n);
        for (int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),Add(u,v);
        cnt=0;DFS(1,-1);
        sort(ans+1,ans+cnt+1);
        for (int i=1;i<=cnt;i++) printf("%d
    ",ans[i]);
        if (!cnt) printf("NONE");
        printf("
    ");
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    P4718 [模板]Pollard-Rho算法
    python爬虫模板
    Codeforces1248F. Catowice City
    P3980 [NOI2008]志愿者招募 (费用流)
    P2805 [NOI2009]植物大战僵尸 (拓扑排序 + 最小割)
    P3157 [CQOI2011]动态逆序对
    P2634 [国家集训队]聪聪可可 (点分治)
    HDU6703 array (线段树)
    Codeforces750E. New Year and Old Subsequence (线段树维护DP)
    Codeforces301D. Yaroslav and Divisors
  • 原文地址:https://www.cnblogs.com/mastervan/p/10975699.html
Copyright © 2011-2022 走看看