题解 luoguP3554 [POI2013]LUK-Triumphal arch

Posted larry-zero

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 luoguP3554 [POI2013]LUK-Triumphal arch相关的知识,希望对你有一定的参考价值。

代码的关键部分

inline void dfs(int u,int fa) {
    int sum=0;
    for(int i=first[u]; i; i=nxt[i]) {
        int v=go[i];
        if(v==fa)continue;
        dfs(v,u);
        sum+=f[v]+1;
    }
  f[u]=max(sum-mid,0);

}

关于这个方程解释一下

f[u]=max(sum-mid,0);

我们不断搜索去边,然后回溯更新每一个阶段需要被染色的数量;

假设需要被染色的节点数量不足k,即sum-mid<0,那我们取0,原因是每次染色的机会是从后往前推的,即使仍然有染色的机会也不能更新前面的状态;

而如果需要染色的节点数量大于k,即sum-mid>0,那么我们显然可以累加到父亲节点,在回溯到父亲节点的时候再统一处理,因为在B点在父亲时是可以对儿子节点进行染色的(前提是sum-mid>0,即仍有染色次数),此处区别于上面那种情况;

所以我们每次二分mid

如果f[1]=0,显然是合法的,我们就缩小mid

AC code:

技术图片
#include<bits/stdc++.h>
using namespace std;
const int N=2000005;
int first[N],nxt[N],go[N],tot,f[N],mid;
void add(int x,int y) {
    nxt[++tot]=first[x];
    first[x]=tot;
    go[tot]=y;
}
inline void dfs(int u,int fa) {
    int sum=0;
    for(int i=first[u]; i; i=nxt[i]) {
        int v=go[i];
        if(v==fa)continue;
        dfs(v,u);
        sum+=f[v]+1;
    }
    f[u]=max(sum-mid,0);
}
int main() {
    int n;
    scanf("%d",&n);
    if(n==1)printf("0"),exit(0);
    for(int i=1,x,y; i<n; i++) {
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    int l=1,r=1<<30,ans=0;
    while (l<r) {
        memset(f,0,sizeof(f));
        mid=(l+r)>>1;
        dfs(1,0);
        if (!f[1])r=mid;
        else l=mid+1;
    }
    printf("%d
",r);
    return 0;
}
View Code

 

以上是关于题解 luoguP3554 [POI2013]LUK-Triumphal arch的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2084/luoguP3501 [Poi2010]Antisymmetry(回文自动机+dp)

2018下半年的刷题列表

[二分查找] [luoguP3500] [POI2010] TES-Intelligence Test

LuoguP3521 [POI2011]ROT-Tree Rotations

luoguP3507 [POI2010]GRA 性质 + 动态规划

LuoguP3469 [POI2008]BLO-Blockade