题解 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; }
以上是关于题解 luoguP3554 [POI2013]LUK-Triumphal arch的主要内容,如果未能解决你的问题,请参考以下文章
bzoj2084/luoguP3501 [Poi2010]Antisymmetry(回文自动机+dp)
[二分查找] [luoguP3500] [POI2010] TES-Intelligence Test
LuoguP3521 [POI2011]ROT-Tree Rotations