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
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    Java中Vector和ArrayList的区别
    多线程
    集合框架
    5种运行时异常+1道面试题
    事务,视图,索引,备份和恢复
    MYSQL常用函数
    SQL数据库表字段明细导入导出
    SqlServer 命令方式备份与还原
    .NetCore IIS发布后PUT、DELETE请求错误405.0
    大数据中HBase的Java接口封装
  • 原文地址:https://www.cnblogs.com/mastervan/p/10975699.html
Copyright © 2011-2022 走看看