#LCA,二分,树上差分#洛谷 2680 运输计划

题目

一棵树,每条边上都有边权,现在选择一条边将边权变为0,使\(m\)条路径边权和其中一条的最大值最小,问这个值


分析

由于大于最终结果的一定可行,小于最终结果的一定不可行,所以二分答案,首先答案以下的需求都不需要考虑,差分,如果该位置上的需求数量等于所需求的数量那么这条边就可以选,但是如果最大值减去这条边仍不能小于等于答案,那么依然是不可行的,或者不可能达到需求数量也是不可行的


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define rr register
using namespace std;
const int N=300011;
struct node{int y,w,next;}e[N<<1];
struct rec{int x,y,Lca,w;}q[N];
int dep[N],fat[N],son[N],big[N],top[N],n,k=1,m,tot,ls[N],w[N],mx,dis[N];
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
bool cmp(const rec &a,const rec &b){return a.w>b.w;} 
inline signed max(int a,int b){return a>b?a:b;} 
inline void dfs1(int x,int fa){
	dep[x]=dep[fa]+1,fat[x]=fa,son[x]=1;
	for (rr int i=ls[x],mson=-1;i;i=e[i].next)
	if (e[i].y!=fa){
		dis[e[i].y]=dis[x]+e[i].w,dfs1(e[i].y,x),son[x]+=son[e[i].y];
		if (son[e[i].y]>mson) big[x]=e[i].y,mson=son[e[i].y];
	}
}
inline void dfs2(int x,int linp){
	top[x]=linp; if (!big[x]) return; dfs2(big[x],linp);
	for (rr int i=ls[x];i;i=e[i].next)
	if (e[i].y!=fat[x]&&e[i].y!=big[x]) dfs2(e[i].y,e[i].y);
}
inline signed lca(int x,int y){
	while (top[x]!=top[y]){
		if (dep[top[x]]<dep[top[y]]) x^=y,y^=x,x^=y;
		x=fat[top[x]];
	}
	if (dep[x]>dep[y]) x^=y,y^=x,x^=y;
	return x;
}
inline void dfs3(int x,int fa){
	for (rr int i=ls[x];i;i=e[i].next)
	if (e[i].y!=fa) dfs3(e[i].y,x),w[x]+=w[e[i].y];
	if (w[x]==tot) mx=max(mx,dis[x]-dis[fat[x]]);
}
inline bool check(int now){
	memset(w,0,sizeof(w)),tot=0,mx=-4e8;
	for (rr int i=1;i<=m&&q[i].w>now;++i)
		++tot,++w[q[i].x],++w[q[i].y],w[q[i].Lca]-=2;
	dfs3(1,0);
	if (mx==-4e8||q[1].w-mx>now) return 0;
	    else return 1;
}
signed main(){
	n=iut(); m=iut();
	for (rr int i=1;i<n;++i){
		rr int x=iut(),y=iut(),w=iut();
		e[++k]=(node){y,w,ls[x]},ls[x]=k,
		e[++k]=(node){x,w,ls[y]},ls[y]=k;
	}
	dfs1(1,0),dfs2(1,0); rr int l=0,r=-4e8;
	for (rr int i=1;i<=m;++i){
		q[i].x=iut(),q[i].y=iut(),q[i].Lca=lca(q[i].x,q[i].y),
		q[i].w=dis[q[i].x]+dis[q[i].y]-2*dis[q[i].Lca],r=max(r,q[i].w);
	}
	sort(q+1,q+1+m,cmp);
	while (l<r){
		rr int mid=(l+r)>>1;
		if (check(mid)) r=mid;
		    else l=mid+1; 
	}
	return !printf("%d",l);
} 

------------恢复内容结束------------

posted @ 2020-01-16 15:28  lemondinosaur  阅读(127)  评论(0编辑  收藏  举报