点分治神题orzorz
首先考虑O(nm)O(nm)的暴力,就是枚举任意点作为邮递站作根,暴力dfsdfs,求出每组配送的最大代价,记作cost_icosti。
那么对于最优点作根,显然对于任意一条从根开始的链,cost_icosti都是递增的
于是我们可以点分治一下,每次做出当前子树的重心,对所有配送都求一遍代价,取maxmax
对于一次配送,若其代价为maxmax,并且两点跨过重心,或者多组配送在重心的不同子树,代价均为maxmax,显然此时是最优点
否则迭代着继续点分治,显然只有loglog次
复杂度为O(mlogn)O(mlogn)
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#define rep(i,s,t) for(register int i=s;i<=t;++i)
#define gi(x) read(x)
#define gii(x,y) read(x),read(y)
#define giii(x,y,z) read(x),read(y),read(z)
#define ms(f,x) memset(f,x,sizeof f)
#define open(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
namespace IO{
#define gc getchar()
#define pc(x) putchar(x)
template<typename T>inline void read(T &x){
x=0;int f=1;char ch=gc;while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=gc;}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=gc;x*=f;return;
}
template<typename T>inline void write(T x=0){
T wr[51];wr[0]=0;if(x<0)pc('-'),x=-x;if(!x)pc(48);
while(x)wr[++wr[0]]=x%10,x/=10;while(wr[0])pc(48+wr[wr[0]--]);return;
}
}
using IO::read;
using IO::write;
using namespace std;
const int N=2e5+11;
int n,m,tot,rt,ans;
int nxt[N],las[N],to[N],w[N],sz[N],f[N],bel[N],dis[N],p[N];
int x[N],y[N];
bool vis[N];
inline void add(int x,int y,int z){
nxt[++tot]=las[x];
las[x]=tot;
to[tot]=y;
w[tot]=z;
}
inline void getroot(int x,int fa,int siz){
sz[x]=1;f[x]=0;
for(register int e=las[x];e;e=nxt[e]){
if(to[e]==fa||vis[to[e]])continue;
getroot(to[e],x,siz);
sz[x]+=sz[to[e]];
f[x]=max(f[x],sz[to[e]]);
}
f[x]=max(f[x],siz-sz[x]);
if(f[x]<f[rt])rt=x;
}
inline void dfs(int x,int fa,int rt){
bel[x]=rt;
for(register int e=las[x];e;e=nxt[e]){
if(to[e]==fa)continue;
dis[to[e]]=dis[x]+w[e];
dfs(to[e],x,rt);
}
}
inline void solve(int u){
if(vis[u]){
printf("%d\n",ans);
exit(0);
}
vis[u]=1,dis[u]=0;
for(register int e=las[u];e;e=nxt[e])
dis[to[e]]=w[e],dfs(to[e],u,to[e]);
int Max=0,las=0;p[0]=0;
rep(i,1,m)
if(dis[x[i]]+dis[y[i]]>Max)
Max=dis[x[i]]+dis[y[i]],p[p[0]=1]=i;
else
if(Max==dis[x[i]]+dis[y[i]])
p[++p[0]]=i;
ans=min(ans,Max);
rep(i,1,p[0])
if(bel[x[p[i]]]!=bel[y[p[i]]]){
printf("%d\n",ans);
exit(0);
}
else{
if(!las)las=bel[x[p[i]]];
else
if(bel[x[p[i]]]!=las){
printf("%d\n",ans);
exit(0);
}
}
rt=0;
getroot(las,u,sz[las]);
solve(rt);
}
int main(){
gii(n,m);
rep(i,2,n){
int u,v,w;
giii(u,v,w);
add(u,v,w),add(v,u,w);
}
rep(i,1,m)
gii(x[i],y[i]);
ans=1e9;
f[rt=0]=n+1;
getroot(1,1,n);
solve(rt);
return 0;
}
啦啦啦啦啦啦啦啦啦啦啦