BZOJ2067[Poi2004]SZN 二分+树上贪心
Posted CQzhangyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2067[Poi2004]SZN 二分+树上贪心相关的知识,希望对你有一定的参考价值。
【BZOJ2067】[Poi2004]SZN
Description
Input
Output
Sample Input
7 8
4 5
5 6
1 2
3 2
9 8
2 5
5 8
Sample Output
HINT
题解:第一问结论好重要啊。
设一个点的度数为d[i],我们统计多少条路径的最高点是这个点。对于非根的点,它肯定有一条路是从父亲那里来的,这条路还能延伸至它的一个儿子。那么对于剩下的儿子,将他们两两配对,剩余的单算,所以这个点对答案的贡献就是$\lceil\frac {d[i]-2} 2\rceil = \lfloor \frac {d[i]-1} 2 \rfloor$。对于根节点,它的贡献是$\lceil\frac {d[1]} 2\rceil$,所以$ans=1+\sum\limits_{i=1}^n\lfloor \frac {d[i]-1} 2 \rfloor$。
第二问的思路与第一问类似,容易想到先二分答案limit,然后令f[i]表示i到父亲那条路径的最短长度是多少。那么f[i]怎么求呢?我们将i的所有儿子的f值拿出来排序,发现i的f值可以二分得到。假如f[i]=f[j]+1,那么我们将j去掉,其余的f值从不断取出最大的和最小的两两配对,如果所有配对后的路径长度都<=limit,则这是一个合法的f值,继续二分即可。
注意:如果一个点的儿子个数是奇数,那么我们需要再添一个f值为0的儿子。根节点的f值需要特殊处理。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=10010; int n,m,ans,cnt,lim,flag; int to[maxn<<1],next[maxn<<1],head[maxn],d[maxn]; int g[maxn],f[maxn]; inline void add(int a,int b) { to[cnt]=b,next[cnt]=head[a],head[a]=cnt++; } bool check(int x) { int i,j; for(i=1,j=m;i<j;i++,j--) { if(i==x) i++; if(j==x) j--; if(g[i]+g[j]>lim) return 0; } return 1; } void dfs(int x,int fa) { int i; for(i=head[x];i!=-1;i=next[i]) if(to[i]!=fa) dfs(to[i],x); for(m=0,i=head[x];i!=-1;i=next[i]) if(to[i]!=fa) g[++m]=f[to[i]]+1; if(x==1) { sort(g+1,g+m+1); flag&=check((m&1)?m:0); return ; } if(!(m&1)) g[++m]=0; sort(g+1,g+m+1); int l=1,r=m+1,mid; while(l<r) { mid=(l+r)>>1; if(g[mid]+1<=lim&&check(mid)) r=mid; else l=mid+1; } if(r==m+1) flag=0; f[x]=g[r]; } inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘) f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+(gc^‘0‘),gc=getchar(); return ret*f; } int main() { n=rd(); int i,a,b,l=1,r=n; memset(head,-1,sizeof(head)); for(i=1;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a),d[a]++,d[b]++; for(ans=i=1;i<=n;i++) ans+=(d[i]-1)>>1; while(l<r) { flag=1,lim=(l+r)>>1,dfs(1,0); if(flag) r=lim; else l=lim+1; } printf("%d %d",ans,r); return 0; }
以上是关于BZOJ2067[Poi2004]SZN 二分+树上贪心的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 1937: [Shoi2004]Mst 最小生成树 [二分图最大权匹配]
[bzoj3037/2068]创世纪[Poi2004]SZP_树形dp_并查集_基环树
题解 bzoj1135: [POI2009]Lyz (线段树+霍尔定理)