• codeforces 709E E. Centroids(树形dp)


    题目链接:

    E. Centroids

    time limit per test
    4 seconds
    memory limit per test
    512 megabytes
    input
    standard input
    output
    standard output

    Tree is a connected acyclic graph. Suppose you are given a tree consisting of n vertices. The vertex of this tree is called centroid if the size of each connected component that appears if this vertex is removed from the tree doesn't exceed .

    You are given a tree of size n and can perform no more than one edge replacement. Edge replacement is the operation of removing one edge from the tree (without deleting incident vertices) and inserting one new edge (without adding new vertices) in such a way that the graph remains a tree. For each vertex you have to determine if it's possible to make it centroid by performing no more than one edge replacement.

    Input

    The first line of the input contains an integer n (2 ≤ n ≤ 400 000) — the number of vertices in the tree. Each of the next n - 1 lines contains a pair of vertex indices ui and vi (1 ≤ ui, vi ≤ n) — endpoints of the corresponding edge.

    Output

    Print n integers. The i-th of them should be equal to 1 if the i-th vertex can be made centroid by replacing no more than one edge, and should be equal to 0 otherwise.

    Examples
    input
    3
    1 2
    2 3
    output
    1 1 1 
    input
    5
    1 2
    1 3
    1 4
    1 5
    output
    1 0 0 0 0 

    题意:

    给出一棵树,要求你最多改变一条边,看这个点能否成为重心;

    思路:

    树形dp,先转化成有根树,第一次dfs先找到每个节点以下的节点数目和能切断的最多的数目以及最多和次多转移来的节点,第二次dfs就是找答案了;
    由于一个那个超过n/2的子树只有一棵,要么来自当前节点的子节点,要么来自父节点,所以在树上进行转移;具体的看代码注释;

    AC代码:
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <bits/stdc++.h>
    #include <stack>
    #include <map>
     
    using namespace std;
     
    #define For(i,j,n) for(int i=j;i<=n;i++)
    #define mst(ss,b) memset(ss,b,sizeof(ss));
     
    typedef  long long LL;
     
    template<class T> void read(T&num) {
        char CH; bool F=false;
        for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
        for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
        F && (num=-num);
    }
    int stk[70], tp;
    template<class T> inline void print(T p) {
        if(!p) { puts("0"); return; }
        while(p) stk[++ tp] = p%10, p/=10;
        while(tp) putchar(stk[tp--] + '0');
        putchar('
    ');
    }
     
    const LL mod=1e9+7;
    const double PI=acos(-1.0);
    const int inf=1e9;
    const int N=4e5+10;
    const int maxn=1e3+20;
    const double eps=1e-12;
    
    
    int n,siz[N],ans[N],submax[N],max1[N],max2[N];
    vector<int>ve[N];
    
    void dfs(int cur,int fa)
    {
        siz[cur]=1;//节点数目
        submax[cur]=0;//submax[cur]是以cur为根的子树能切掉的最大的节点数目,
        int len=ve[cur].size();
        for(int i=0;i<len;i++)
        {
            int x=ve[cur][i];
            if(x==fa)continue;
            dfs(x,cur);
            siz[cur]+=siz[x];
            if(submax[x]>submax[cur])
            {
                max2[cur]=max1[cur];//max2[cur]记录次大,max1[cur]记录最大;
                max1[cur]=x;
                submax[cur]=submax[x];
            }
            else if(submax[x]>submax[max2[cur]])max2[cur]=x;
        }
        if(siz[cur]<=n/2)submax[cur]=siz[cur];
    }
    void dfs1(int cur,int fa,int mmax)
    {
        int len=ve[cur].size(),flag=1;
        for(int i=0;i<len;i++)
        {
            int x=ve[cur][i];
            if(x==fa)//父节点转移过来
            {
                int temp=n-siz[cur];
                if(temp>n/2&&temp-mmax>n/2)flag=0;
                continue;
            }
            if(siz[x]>n/2)//子节点转移过来
            {
                if(siz[x]-submax[x]>n/2)flag=0;
            }
        }
        ans[cur]=flag;
        for(int i=0;i<len;i++)
        {
            int x=ve[cur][i];
            if(x==fa)continue;
            int temp;
            if(n-siz[x]<=n/2)temp=n-siz[x];
            else 
            {
                if(max1[cur]==x)temp=max(mmax,submax[max2[cur]]);//如果x正好是最大的转移过来的就取mmax和次大的最大值
                else temp=max(mmax,submax[max1[cur]]);//否则取mmax与最大的最大值
            }
            dfs1(x,cur,temp);
        }
    }
    int main()
    {
        read(n);
        int u,v;
        For(i,1,n-1)
        {
            read(u);read(v);
            ve[v].push_back(u);
            ve[u].push_back(v);
        }
        dfs(1,0);
        dfs1(1,0,0);
        for(int i=1;i<=n;i++)printf("%d ",ans[i]);
        return 0;
    }
    

      




  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    初识面向对象编程(Object Oriented Programming,OOP)
    详述WebLogic反序列化远程命令执行漏洞的处理过程,云和恩墨技术通讯精选
    分布式监控系统zipkin介绍
    Uncaught TypeError: Cannot set property 'render' of undefined
    python PIL的Image.resize()和Image.thumbnail()函数的区别
    dump 组合索引存储null值
    史上最全MySQL锁机制
    Dump 组合索引
  • 原文地址:https://www.cnblogs.com/zhangchengc919/p/5808506.html
Copyright © 2020-2023  润新知