首页 > 代码库 > BZOJ 2097 Exercise 奶牛健美操 二分答案+树形DP+贪心
BZOJ 2097 Exercise 奶牛健美操 二分答案+树形DP+贪心
题目大意:给定一棵树,可以删掉k条边,求删掉后森林中所有树直径的最大值的最小值
最大值最小,典型的二分答案
此题我们二分树的直径,每次二分DFS一次,对于每个节点统计出所有子树删边后的dis,排序,贪心删掉最大的,直到最大的两个子树相加不会超过二分的答案为止
时间复杂度O(nlog^2n)
老子的二分居然写挂了。。。桑不起啊啊啊啊
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 100100 using namespace std; struct abcd{ int to,next; }table[M<<1]; int head[M],tot; int n,m,ans; int fa[M],dis[M],stack[M],top; void Add(int x,int y) { table[++tot].to=y; table[tot].next=head[x]; head[x]=tot; } void Tree_DP(int x,int limit) { int i,bottom=top; for(i=head[x];i;i=table[i].next) { if(table[i].to==fa[x]) continue; fa[table[i].to]=x; Tree_DP(table[i].to,limit); stack[++top]=dis[table[i].to]+1; } sort(stack+bottom+1,stack+top+1); for(i=top;i>bottom;i--) if(stack[i]>limit||i>bottom+1&&stack[i]+stack[i-1]>limit) ++ans; else break; dis[x]=i==bottom?0:stack[i]; top=bottom; } int Bisection() { int l=1,r=n; while(l+1<r) { int mid=l+r>>1; ans=0;Tree_DP(1,mid); if(ans>m) l=mid; else r=mid; } ans=0;Tree_DP(1,l); if(ans<=m) return l; return r; } int main() { int i,x,y; cin>>n>>m; for(i=1;i<n;i++) scanf("%d%d",&x,&y),Add(x,y),Add(y,x); printf("%d\n", Bisection() ); }
BZOJ 2097 Exercise 奶牛健美操 二分答案+树形DP+贪心
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。