社区讨论

90分求助

P2680[NOIP 2015 提高组] 运输计划参与者 4已保存回复 5

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
5 条
当前快照
1 份
快照标识符
@mi7clagx
此快照首次捕获于
2025/11/20 19:28
4 个月前
此快照最后确认于
2025/11/20 19:28
4 个月前
查看原帖
CPP
#include<bits/stdc++.h>
#define LL long long
#define MaxN 500001
#define Swap(x,y) x^=y,y^=x,x^=y
#define il inline
using namespace std;
int n,m,Head[MaxN],Cnt,Depth[MaxN],F[MaxN][21];
LL Dis[MaxN],MaxLen;
struct Xjh{
    int Ver,Next;
    LL Weight;
}E[MaxN<<1];
struct Hrz{
    int x,y;
    LL Length;
}A[MaxN];
bool operator < (Hrz x,Hrz y){
    return x.Length<y.Length;
}
il void Add_Edge(int x,int y,LL z){
    E[++Cnt].Ver=y;
    E[Cnt].Weight=z;
    E[Cnt].Next=Head[x];
    Head[x]=Cnt;
}
il void Dfs(int u,int f,int Dep){
    F[u][0]=f;
    Depth[u]=Dep;
    for(int i=Head[u],v;i;i=E[i].Next)
        if((v=E[i].Ver)!=f){
            Dis[v]=Dis[u]+E[i].Weight;
            Dfs(v,u,Dep+1);
        }
}
il int LCA(int x,int y){
    if(Depth[x]<Depth[y])
        Swap(x,y);
    for(int k=20;~k;--k)
        if(Depth[F[x][k]]>=Depth[y])
            x=F[x][k];
    if(x==y)
        return x;
    for(int k=20;~k;--k)
        if(F[x][k]!=F[y][k])
            x=F[x][k],y=F[y][k];
    return F[x][0];
}
il LL D(int x,int y){
    int z=LCA(x,y);
    return Dis[x]+Dis[y]-2*Dis[z];
}
il void Init(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;++i){
        int x,y;
        LL z;
        scanf("%d%d%lld",&x,&y,&z);
        Add_Edge(x,y,z);
        Add_Edge(y,x,z);
    }
    Dfs(1,1,1);
    for(int k=1;k<=20;++k)
        for(int i=1;i<=n;++i)
            F[i][k]=F[F[i][k-1]][k-1];
    for(int i=1;i<=m;++i){
        scanf("%d%d",&A[i].x,&A[i].y);
        A[i].Length=D(A[i].x,A[i].y);
        MaxLen=max(MaxLen,A[i].Length);
    }
    sort(A+1,A+1+m);
}
int S,Tot[MaxN],Now[MaxN];
LL Max;
il void Dfs2(int u,int f){
    for(int i=Head[u],v;i;i=E[i].Next)
        if((v=E[i].Ver)!=f){
            Dfs2(v,u);
            Now[u]+=Now[v];
            if(Now[v]==S)
            	Max=max(Max,E[i].Weight);
        }
    Now[u]+=Tot[u];
}
il bool Judge(int Ret){
	Max=0;
	int MN=1;
	while(A[MN].Length<=Ret)
		++MN;
	S=m-MN+1;
	if(S<=0)
		return true;
	memset(Tot,0,sizeof(Tot));
	memset(Now,0,sizeof(Now));
	int x,y,z;
	for(int i=MN;i<=m;++i){
		x=A[i].x;
		y=A[i].y;
		z=LCA(x,y);
		++Tot[x];
		++Tot[y];
		Tot[z]-=2;
	}
	Dfs2(1,1);
	if(A[m].Length-Max>Ret)
		return false;
	return true;
}
il void Doit(){
    int l=0,r=MaxLen;
    int Mid;
    LL Ans;
    while(l<=r){
        Mid=(l+r)>>1;
        if(Judge(Mid))
            r=Mid-1,Ans=Mid;
        else
            l=Mid+1;
    }
    printf("%lld\n",Ans);
}
int main(){
    Init();
    Doit();
    return 0;
}

回复

5 条回复,欢迎继续交流。

正在加载回复...