[BZOJ] 4326: NOIP2015 运输计划
二分答案,把原问题转化为\(log\)个判定问题
现在问题是,给出一个答案\(t\),问是否可行
我们找出\(len>t\)的所有路径,这些路径都要被变短,也就要找到这些路径的一条最长公共边
如何找最长公共边?先考虑公共边,可以用树上差分解决,最长就顺便取max即可
//Stay foolish,stay hungry,stay young,stay simple
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cctype>
using namespace std;
inline int rd(){
int ret=0;char c;
while(c=getchar(),!isdigit(c));
while(isdigit(c))ret=ret*10+c-'0',c=getchar();
return ret;
}
const int MAXN =300005,M=300005;
int n,m;
struct Edge{
int nex,to,w;
}e[M<<1];
int ecnt,head[MAXN];
inline void add(const int x,const int y,const int w){
e[++ecnt].nex = head[x];
e[ecnt].to = y;
e[ecnt].w = w;
head[x] = ecnt;
}
int fa[MAXN],hs[MAXN],dep[MAXN];
int dfs1(int x,int pre,int w){
fa[x]=pre;dep[x]=dep[pre]+w;
int mx=0,tmp,siz=1;
for(register int i=head[x];i;i=e[i].nex){
int v=e[i].to;
if(v==pre) continue;
tmp=dfs1(v,x,e[i].w);siz+=tmp;
if(tmp>mx){mx=tmp;hs[x]=v;}
}
return siz;
}
int top[MAXN];
void dfs2(int x,int tp){
top[x]=tp;
if(hs[x]) dfs2(hs[x],tp);
for(register int i=head[x];i;i=e[i].nex){
int v=e[i].to;
if(v==fa[x]||v==hs[x]) continue;
dfs2(v,v);
}
}
int lca(int x,int y){
while(top[x]!=top[y])
dep[top[x]]<dep[top[y]]?y=fa[top[y]]:x=fa[top[x]];
return dep[x]<dep[y]?x:y;
}
struct Links{
int x,y,l,len;
}lk[MAXN];
int num,mx,val[MAXN];
int d[MAXN];
void gfs(int x){
for(register int i=head[x];i;i=e[i].nex){
int v=e[i].to;
if(v==fa[x]) continue;
gfs(v);
d[x]+=d[v];
}
if(d[x]==num){
mx=max(mx,dep[x]-dep[fa[x]]);
}
}
bool check(int t){
num=0;mx=0;
memset(d,0,sizeof(d));
int mxl=0;
for(register int i=1;i<=m;i++){
if(lk[i].len>t){
num++;
d[lk[i].x]++;
d[lk[i].y]++;
d[lk[i].l]-=2;
mxl=max(mxl,lk[i].len);
}
}
gfs(1);
return (mxl-mx<=t);
}
signed main(){
n=rd();m=rd();
int x,y,w;
for(register int i=1;i<=n-1;i++){
x=rd();y=rd();w=rd();
add(x,y,w);add(y,x,w);
}
dfs1(1,0,0);dfs2(1,1);
for(register int i=1;i<=m;i++){
x=lk[i].x=rd();
y=lk[i].y=rd();
int l=lca(x,y);
lk[i].l=l;
lk[i].len=dep[x]+dep[y]-(dep[l]<<1);
}
int l=0,r=3e8,mid,ans;
while(l<=r){
mid=(l+r)>>1;
if(check(mid))ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans;
return 0;
}
本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9781607.html