题解——洛谷 P2680 NOIP提高组 2015 运输计划

时间:2023-03-09 00:20:33
题解——洛谷 P2680 NOIP提高组 2015 运输计划

树上差分加上二分答案

详细题解待填坑

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXlog = ;
const int MAXM = ;
const int MAXN = ;
int dep[MAXN],jump[MAXN][MAXlog+];
int lcav[MAXM],cf[MAXN],fw[MAXN],lent[MAXN];
int uline[MAXM],vline[MAXM],wline[MAXM];
int cnt=,u[MAXN*],v[MAXN*],w[MAXN*],first[MAXN*],next[MAXN*];
int n,m;
void addline(int ux,int vx,int i){
uline[i]=ux;
vline[i]=vx;
wline[i]=lent[ux]+lent[vx]-*lent[lcav[i]];
}
void addedge(int ux,int vx,int wx){
cnt++;
u[cnt]=ux;
v[cnt]=vx;
w[cnt]=wx;
next[cnt]=first[ux];
first[ux]=cnt;
}
void dfs(int u,int f){
// printf("u=%d f=%d\n",u,f);
dep[u]=dep[f]+;
jump[u][]=f;
// printf("u=%d j=0 jump=%d\n",u,jump[u][0]);
for(int i=;i<=MAXlog;i++){
jump[u][i]=jump[jump[u][i-]][i-];
// printf("u=%d j=%d jump=%d\n",u,i,jump[u][i]);
}
for(int i=first[u];i;i=next[i])
if(v[i]!=f)
dfs(v[i],u);
}
void dfs2(int u,int f,int wk){
fw[u]=wk;
lent[u]=lent[f]+wk;
for(int i=first[u];i;i=next[i])
if(v[i]!=f)
dfs2(v[i],u,w[i]);
}
int lca(int x,int y){
if(dep[y]>dep[x])
swap(x,y);
for(int i=MAXlog;i>=;i--)
if(dep[x]-(<<i)>=dep[y])
x=jump[x][i];
if(x==y)
return x;
for(int i=MAXlog;i>=;i--)
if(jump[x][i]!=jump[y][i]){
x=jump[x][i];
y=jump[y][i];
}
return jump[x][];
}
void runcf(int l){
cf[uline[l]]++;
cf[vline[l]]++;
cf[lcav[l]]-=;
}
int maxlen=;
void calcf(int u,int f,int num){
for(int i=first[u];i;i=next[i]){
if(v[i]==f)
continue;
calcf(v[i],u,num);
cf[u]+=cf[v[i]];
}
if(cf[u]==num&&fw[u]>maxlen)
maxlen=fw[u];
}
bool check(int ans){
int inq=;
int maxchain=;
maxlen=;
// printf("!ok\n");
memset(cf,,sizeof(cf));
for(int i=;i<=cnt;i++)
if(wline[i]>ans){
runcf(i);
inq++;
if(wline[i]>maxchain)
maxchain=wline[i];
} calcf(,,inq);
// printf("*ok\n");
if(maxchain-maxlen<=ans)
return true;
else
return false;
}
int main(){
scanf("%d %d",&n,&m);
int maxt=;
for(int i=;i<=n-;i++){
int a,b,t;
scanf("%d %d %d",&a,&b,&t);
addedge(a,b,t);
addedge(b,a,t);
maxt=max(maxt,t);
}
dep[]=-;
dfs(,);
dfs2(,,);
int maxline=;
for(int i=;i<=m;i++){
int um,vm;
scanf("%d %d",&um,&vm);
// if(jump[5][0]!=3)
// printf("!\n");
lcav[i]=lca(um,vm);
addline(um,vm,i);
if(wline[i]>maxline)
maxline=wline[i];
}
/*for(int i=0;i<=n;i++){
for(int j=0;j<=MAXlog;j++)
printf("jump[%d][%d]=%d \n",i,j,jump[i][j]);
printf("\n");
}*/
/*for(int i=1;i<=m;i++){
printf("u=%d v=%d lca=%d len=%d\n",uline[i],vline[i],lcav[i],wline[i]);
}*/
int l=maxline-maxt,r=maxline+;
while(l<r){
int mid=(l+r)>>;
if(check(mid))
r=mid;
else
l=mid+;
}
printf("%d",r);
return ;
}