#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);
}
------------恢复内容结束------------