zoukankan      html  css  js  c++  java
  • 洛谷P4228 [清华集训2017] 榕树之心

    先只考虑根节点是否合法。发现两个来自不同子树的点可以消去,那么只需判定所有点能否两两消去,使心停留在根节点即可。

    发现其可以转化为一个模型:有若干个集合,每个集合内有若干个点,每次可以消去两个来自不同集合的点。设集合点数总和为 (sum),最大集合点数为 (max),得:

    (sum-max geqslant max) 时,即 (sum geqslant 2max),若 (sum) 为偶数则能消完,否则会剩下 (1) 个点,消去了 (left lfloor frac{sum}{2} ight floor) 对。

    否则会剩下 (max-(sum-max)) 个来自最大集合的点,消去了 (sum-max) 对。

    然后将该模型应用到本题,设 (f_x) 为点 (x) 子树内能最多消去多少对点,点 (y) 为点 (x) 儿子中子树大小最大的儿子,得当 (size_x-1 geqslant 2(size_y-f_y)) 时,(f_x=left lfloor frac{size_x-1}{2} ight floor),否则 (f_x=size_x-1-(size_y-f_y))

    然后考虑如何判定其他节点合法,可以看作心先从根节点移动到了当前节点,那么将根节点到当前节点的链缩成一个点即可。这里需要知道缩点后的最大子树,因此还需处理出每个节点的次大子树。

    通过 (sum geqslant 2max) 是否满足和总点数与当前节点深度的奇偶性是否相同来判定即可。

    #include<bits/stdc++.h>
    #define maxn 200010
    using namespace std;
    template<typename T> inline void read(T &x)
    {
        x=0;char c=getchar();bool flag=false;
        while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        if(flag)x=-x;
    }
    int type,T,n;
    int f[maxn],siz[maxn],dep[maxn],son1[maxn],son2[maxn],ans[maxn];
    struct edge
    {
        int to,nxt;
    }e[maxn];
    int head[maxn],edge_cnt;
    void add(int from,int to)
    {
        e[++edge_cnt]={to,head[from]},head[from]=edge_cnt;
    }
    void dfs1(int x,int fa)
    {
        siz[x]=1,dep[x]=dep[fa]+1,son1[x]=son2[x]=0;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(y==fa) continue;
            dfs1(y,x),siz[x]+=siz[y];
            if(siz[y]>siz[son1[x]]) son2[x]=son1[x],son1[x]=y;
            else if(siz[y]>siz[son2[x]]) son2[x]=y;
        }
        if(!son1[x]) return;
        if(siz[x]-1>=2*(siz[son1[x]]-f[son1[x]])) f[x]=(siz[x]-1)/2;
        else f[x]=siz[x]-1-siz[son1[x]]+f[son1[x]];
    }
    int c(int x,int y)
    {
        return siz[x]>siz[y]?x:y;
    }
    void dfs2(int x,int fa,int p)
    {
        int t=c(p,son1[x]);
        if(n-dep[x]>=2*(siz[t]-f[t])) ans[x]=(n&1)==(dep[x]&1);
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(y==fa) continue;
            dfs2(y,x,y==son1[x]?c(p,son2[x]):c(p,son1[x]));
        }
    }
    void clear()
    {
        edge_cnt=0;
        memset(head,0,sizeof(head));
        memset(ans,0,sizeof(ans));
    }
    int main()
    {
        read(type),read(T);
        while(T--)
        {
            clear(),read(n);
            for(int i=1;i<n;++i)
            {
                int x,y;
                read(x),read(y);
                add(x,y),add(y,x);
            }
            dfs1(1,0),dfs2(1,0,0);
            if(type==3) printf("%d",ans[1]);
            else for(int i=1;i<=n;++i) printf("%d",ans[i]);
            putchar('
    ');
        }
        return 0;
    }
    
  • 相关阅读:
    LeetCode题解之Flipping an Image
    LeetCode 之Find Minimum in Rotated Sorted Array
    LeetCode题解Transpose Matrix
    LeetCode 题解之Minimum Index Sum of Two Lists
    LeetCode题解之Intersection of Two Linked Lists
    LeetCode 题解之Add Two Numbers II
    LeetCode题解之Add two numbers
    href="#"与href="javascript:void(0)"的区别
    有关ie9 以下不支持placeholder属性以及获得焦点placeholder的移除
    ie7下属性书写不规范造成的easyui 弹窗布局紊乱
  • 原文地址:https://www.cnblogs.com/lhm-/p/13782912.html
Copyright © 2011-2022 走看看