CodeForces - 1004E Sonya and Ice Cream

题面在这里!

 

挺智障的一个二分。。。我还写了好久QWQ,退役算啦

题解见注释。。。

/*
    先对每个点记录 向子树外的最长路 和 向子树内最长路,然后二分。
	二分的时候枚举链的LCA直接做就好啦。  
*/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define pb push_back
const int N=100005,B=2333333;

inline int read(){
	int x=0; char ch=getchar();
	for(;!isdigit(ch);ch=getchar());
	for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
	return x;
}

int to[N*2],ne[N*2],val[N*2],num,mid,d[N];
int hd[N],n,m,f[N],dn[N],dw[N],k,ans;
bool flag;

inline void add(int x,int y,int z){
	to[++num]=y,ne[num]=hd[x],hd[x]=num,val[num]=z;
}

void fdfs(int x,int fa){
	for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa)
		fdfs(to[i],x),dn[x]=max(dn[x],dn[to[i]]+val[i]);
}

void sdfs(int x,int fa,int L){
	int D=d[x],qz[D+1],hz[D+1];
	dw[x]=qz[0]=hz[0]=L;
	
	for(int i=hd[x],j=0;i;i=ne[i]) if(to[i]!=fa){
		j++,qz[j]=hz[j]=dn[to[i]]+val[i];
	}
	
	for(int i=1;i<D;i++) qz[i]=max(qz[i],qz[i-1]);
	hz[D]=0;
	for(int i=D-1;i;i--) hz[i]=max(hz[i],hz[i+1]);
	
	for(int i=hd[x],j=0;i;i=ne[i]) if(to[i]!=fa){
		j++,sdfs(to[i],x,max(qz[j-1],hz[j+1])+val[i]);
	}
}

void dfs(int x,int fa){
	int M=0,C=0;
	for(int i=hd[x];i;i=ne[i]) if(to[i]!=fa){
		dfs(to[i],x);
		if(dn[to[i]]+val[i]>mid){
			if(!M) M=f[to[i]];
			else if(!C) C=f[to[i]];
			else{ M=C=k; break;}
		}
	}
	
	f[x]=C?k:M+1;
	flag|=(dw[x]<=mid&&M+C<k);
}

inline bool solve(){
	memset(f,0,sizeof(f)),flag=0;
	dfs(1,0); return flag;
}

int main(){
	n=read(),k=read();
	for(int i=1,uu,vv,ww;i<n;i++){
		uu=read(),vv=read(),ww=read();
		add(uu,vv,ww),add(vv,uu,ww);
		d[uu]++,d[vv]++;
	}
	
	fdfs(1,0),d[1]++,sdfs(1,0,0);
	
	int L=0,R=1e9;
	while(L<=R){
		mid=L+R>>1;
		if(solve()) ans=mid,R=mid-1;
		else L=mid+1;
	}
	
	printf("%d\n",ans);
	return 0;
}

  

posted @ 2018-07-08 18:49  蒟蒻JHY  阅读(445)  评论(1编辑  收藏  举报