社区讨论
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 条回复,欢迎继续交流。
正在加载回复...