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('\n');
}
 
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;
}

  




转载于:https://www.cnblogs.com/zhangchengc919/p/5808506.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,Codeforces Round 511 (Div. 1)是一个比赛的名称。然而,引用内容中没有提供与这个比赛相关的具体信息或问题。因此,我无法回答关于Codeforces Round 511 (Div. 1)的问题。如果您有关于这个比赛的具体问题,请提供更多的信息,我将尽力回答。 #### 引用[.reference_title] - *1* [Codeforces Round 860 (Div. 2)题解](https://blog.csdn.net/qq_60653991/article/details/129802687)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Codeforces Round 867 (Div. 3)(A题到E题)](https://blog.csdn.net/wdgkd/article/details/130370975)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Codeforces Round 872 (Div. 2)(前三道](https://blog.csdn.net/qq_68286180/article/details/130570952)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值