LOJ2425 NOIP2015 運輸計劃 【二分+LCA+樹上差分】*
阿新 • • 發佈:2018-12-09
LOJ2425 NOIP2015 運輸計劃
題意:給你一顆樹,可以將任意一條邊的權值變成0,然後求m條路徑的長度的最小值
思路: 先二分最後的距離ans,然後我們把路程大於ans的所有路徑拿出來 然後把這些路徑的交求出來,用樹上差分的方法 然後對這個交(用點集轉化成邊集,就是每個點的上一條邊)取一個最大值 然後判斷這些邊減去這個最大值之後會不會小於等於ans
#include<bits/stdc++.h>
using namespace std;
#define fu(a,b,c) for(int a=b;a<=c;++a)
#define fd(a,b,c) for(int a=b;a>=c;--a)
int read(){
int ans=0,w=1;char c=getchar();
while(!isdigit(c)&&c!='-')c=getchar();
if(c=='-')w=-1,c=getchar();
while(isdigit(c))ans=(ans<<1)+(ans<<3)+c-'0',c=getchar();
return ans*w;
}
const int N=3e5+10;
struct Edge{int v,w,next;}E[N<<1];
int head[N],tot=0;
int n,m,l=0 ,r=0;
int cost[N],fro[N],to[N],lca[N];
int dis[N],dep[N],cnt[N],pre[N];
int fa[N][20],Log2[N];
void add(int u,int v,int w){E[++tot]=(Edge){v,w,head[u]};head[u]=tot;}
void dfs(int u){
dep[u]=dep[fa[u][0]]+1;
fu(i,1,Log2[dep[u]])fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=head[u];i;i=E[i].next){
int v=E[i].v;
if(v==fa[u][0])continue;
pre[v]=i;
fa[v][0]=u;
dis[v]=dis[u]+E[i].w;
dfs(v);
}
}
void redfs(int u){
for(int i=head[u];i;i=E[i].next){
int v=E[i].v;
if(v==fa[u][0])continue;
redfs(v);
cnt[u]+=cnt[v];
}
}
int LCA(int x,int y){
if(dep[x]<dep[y])swap(x,y);
int t=dep[x]-dep[y];
fu(i,0,Log2[t])if(t&(1<<i))x=fa[x][i];
if(x==y)return x;
int k=Log2[dep[x]];
while(fa[x][0]!=fa[y][0]){
if(fa[x][k]!=fa[y][k]){
x=fa[x][k];
y=fa[y][k];
}
k--;
}
return fa[x][0];
}
bool check(int vl){
int siz=0;
fu(i,1,n)cnt[i]=0;
fu(i,1,m){
if(cost[i]<=vl)continue;
siz++;
cnt[fro[i]]++;
cnt[to[i]]++;
cnt[lca[i]]-=2;
}
redfs(1);
int maxv=0;
fu(i,1,n){
if(cnt[i]!=siz)continue;
maxv=max(maxv,E[pre[i]].w);
}
fu(i,1,m)if(cost[i]-maxv>vl)return 0;
return 1;
}
int main(){
n=read();m=read();
Log2[1]=0;fu(i,2,n)Log2[i]=Log2[i>>1]+1;
fu(i,1,n-1){
int u=read(),v=read(),w=read();
add(u,v,w);
add(v,u,w);
}
dfs(1);
fu(i,1,m){
fro[i]=read(),to[i]=read();
lca[i]=LCA(fro[i],to[i]);
cost[i]=dis[fro[i]]+dis[to[i]]-(dis[lca[i]]<<1);
r=max(r,cost[i]);
}
int ans;
while(l<=r){
int mid=(l+r*2)/3;
if(check(mid))r=mid-1,ans=mid;
else l=mid+1;
}
printf("%d",ans);
return 0;
}