• BZOJ 2097 [Usaco2010 Dec]Exercise 奶牛健美操


    【题意】

      给出一棵树。现在可以在树中删去m条边,使它变成m+1棵树。要求最小化树的直径的最大值。

    【题解】

      二分答案。$Check$的时候用$DP$,记录当前节点每个儿子的直径$v[i]$,如果$v[i]+1>mid$,那么就断掉连向儿子的这条边。如果$v[i]+v[j]+2>mid$,那么在i与j中选择一个$v%值较大的断掉。

      

    #include<cstdio>
    #include<algorithm>
    #define N 200010
    #define rg register
    using namespace std;
    int n,m,tot,ans,cut,last[N],mid,f[N],a[N];
    struct edge{
    	int to,pre;
    }e[N];
    inline int read(){
    	int k=0,f=1; char c=getchar();
    	while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    	while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    	return k*f;
    }
    inline void add(int x,int y){
    	e[++tot]=(edge){y,last[x]};
    	last[x]=tot;
    }
    void dfs(int x,int fa){
    	f[x]=0;
    	for(rg int i=last[x],to;i;i=e[i].pre)
    		if((to=e[i].to)!=fa) dfs(to,x);
    	int cnt=0;
    	for(rg int i=last[x],to;i;i=e[i].pre)
    		if((to=e[i].to)!=fa) a[++cnt]=f[to]+1;
    	sort(a+1,a+cnt+1);
    	while(a[cnt]+a[cnt-1]>mid) cut++,cnt--;
    	f[x]=a[cnt];
    }
    bool check(){
    	cut=0;
    	dfs(1,0);
    	//printf("mid=%d cut=%d
    ",mid,cut);
    	if(cut<=m) return 1;
    	return 0;
    }
    int main(){
    	n=read(); m=read();
    	for(rg int i=1,u,v;i<n;i++){
    		u=read(); v=read();
    		add(u,v); add(v,u);
    	}
    	int l=0,r=n-1;
    	while(l<r){
    		mid=(l+r)>>1;
    		if(check()) r=mid;
    		else l=mid+1;
    	}
    	printf("%d
    ",l);
    	return 0;
    }
    

      

  • 相关阅读:
    pythonchallenge 解谜 Level 6
    pythonchallenge 解谜 Level 5
    pythonchallenge 解谜 Level 4
    pythonchallenge 解谜 Level 3
    pythonchallenge 解谜 Level 2
    pythonchallenge 解谜 Level 1
    CCF 201912-2 回收站选址
    JavaWeb+JDBC+Servlet+SqlServer实现登录功能
    后台连接数据库的方法
    jQuery实现轮播图
  • 原文地址:https://www.cnblogs.com/DriverLao/p/8516340.html
Copyright © 2020-2023  润新知