P2680 [NOIP 2015 提高组] 运输计划

//https://www.luogu.com.cn/problem/P2680
#include <bits/stdc++.h>
#pragma G++ optimize(3)
#pragma G++ target("avx")
#pragma G++ optimize("Ofast")
#pragma G++ optimize("inline")
#pragma G++ optimize("-fgcse")
#pragma G++ optimize("-fgcse-lm")
#pragma G++ optimize("-fipa-sra")
#pragma G++ optimize("-ftree-pre")
#pragma G++ optimize("-ftree-vrp")
#pragma G++ optimize("-fpeephole2")
#pragma G++ optimize("-ffast-math")
#pragma G++ optimize("-fsched-spec")
#pragma G++ optimize("unroll-loops")
#pragma G++ optimize("-falign-jumps")
#pragma G++ optimize("-falign-loops")
#pragma G++ optimize("-falign-labels")
#pragma G++ optimize("-fdevirtualize")
#pragma G++ optimize("-fcaller-saves")
#pragma G++ optimize("-fcrossjumping")
#pragma G++ optimize("-fthread-jumps")
#pragma G++ optimize("-funroll-loops")
#pragma G++ optimize("-fwhole-program")
#pragma G++ optimize("-freorder-blocks")
#pragma G++ optimize("-fschedule-insns")
#pragma G++ optimize("inline-functions")
#pragma G++ optimize("-ftree-tail-merge")
#pragma G++ optimize("-fschedule-insns2")
#pragma G++ optimize("-fstrict-aliasing")
#pragma G++ optimize("-fstrict-overflow")
#pragma G++ optimize("-falign-functions")
#pragma G++ optimize("-fcse-skip-blocks")
#pragma G++ optimize("-fcse-follow-jumps")
#pragma G++ optimize("-fsched-interblock")
#pragma G++ optimize("-fpartial-inlining")
#pragma G++ optimize("no-stack-protector")
#pragma G++ optimize("-freorder-functions")
#pragma G++ optimize("-findirect-inlining")
#pragma G++ optimize("-fhoist-adjacent-loads")
#pragma G++ optimize("-frerun-cse-after-loop")
#pragma G++ optimize("inline-small-functions")
#pragma G++ optimize("-finline-small-functions")
#pragma G++ optimize("-ftree-switch-conversion")
#pragma G++ optimize("-foptimize-sibling-calls")
#pragma G++ optimize("-fexpensive-optimizations")
#pragma G++ optimize("-funsafe-loop-optimizations")
#pragma G++ optimize("inline-functions-called-once")
#pragma G++ optimize("-fdelete-null-pointer-checks")
using namespace std;
const int N=3e5+10,M=N*2;
int e[M],ne[M],h[N],idx,w[M];
int depth[N],fa[N][20];
int q[N],pos,order[N];
int n,m;
int d[N];
int Max;
int dist[N];
int u[N],v[N];
int distEdge[N];
int lca_list[N];
void add(int a,int b,int c){
	e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x*f;
}
void write(int x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10+'0');
}
void bfs(int root){
    memset(depth,0x3f,sizeof depth);
    depth[0]=0,depth[root]=1;
    int hh=0,tt=1;
    q[0]=root;
    order[pos++]=root;
    while(hh<tt){
        int u=q[hh++];
        for(int i=h[u];~i;i=ne[i]){
            int v=e[i];
            if(depth[v]>depth[u]+1){
                depth[v]=depth[u]+1;
                dist[v]=dist[u]+w[i];
                q[tt++]=v;
				order[pos++]=v;
                fa[v][0]=u;
                for(int k=1;k<=19;k++) fa[v][k]=fa[fa[v][k-1]][k-1];
            }
        }
    }
}
int lca(int a,int b){
    if(depth[a]<depth[b]) swap(a,b);
    for(int k=19;k>=0;k--) if(depth[fa[a][k]]>=depth[b]) a=fa[a][k];
    if(a==b) return a;
    for(int k=19;k>=0;k--){
        if(fa[a][k]!=fa[b][k]){
            a=fa[a][k],b=fa[b][k];
        }
    }
    return fa[a][0];
}
bool check(int mid){
	int cnt=0;
	memset(d,0,sizeof d);
	for(int i=1;i<=m;i++){
		if(distEdge[i]>mid){
			cnt++;
			d[u[i]]++;
			d[v[i]]++;
			d[lca_list[i]]-=2;
		}
	}
	if(cnt==0) return true;
	for(int i=pos-1;i>=0;i--){
		int u=order[i];
		d[fa[u][0]]+=d[u];
	}
	int res=0;
	for(int i=2;i<=n;i++){
		if(d[i]>=cnt) res=max(res,dist[i]-dist[fa[i][0]]);
	}
	if(Max-res<=mid) return true;
	else return false;
}
int main(){
	memset(h,-1,sizeof h);
	n=read(),m=read();
	for(int i=0,u,v,w;i<n-1;i++){
		u=read(),v=read(),w=read();
		add(u,v,w),add(v,u,w);
	}
	bfs(1);
	for(int i=1;i<=m;i++){
		u[i]=read(),v[i]=read();
		lca_list[i]=lca(u[i],v[i]);
		distEdge[i]=dist[u[i]]+dist[v[i]]-2*dist[lca_list[i]];
		Max=max(Max,distEdge[i]);
	}
	int l=0,r=Max,ans=Max;
	while(l<=r){
		int mid=l+r>>1;
		if(check(mid)){
			r=mid-1;
			ans=mid;
		}else{
			l=mid+1;
		}
	}
	write(ans);
	return 0;
}
posted @ 2025-05-10 12:11  九三青梧  阅读(8)  评论(0)    收藏  举报