NOIP2015提高組Day2T3- 運輸計劃
阿新 • • 發佈:2018-12-30
Tips
如果兩個點的LCA會被反覆用到,就可以拿一個數組存下來,避免反覆計算
Analysis
又是一道好喵喵喵妙的題啊!!!樹上差分太棒了,簡直太厲害
不過首先我們得看出來這是一道二分可以解決的問題
然後問題就變成了怎麼check
看看gsj大佬怎麼說吧
Code
注意常數因子帶來的程式效率上的影響。
所以樹鏈剖分貌似要快得多
但……hhh,寫的倍增
#include<bits/stdc++.h>
#define in read()
#define N 600009
#define M 600009
using namespace std;
inline int read(){
char ch;int f=1,res=0;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
while(ch>='0'&&ch<='9') {
res=(res<<3)+(res<<1)+ch-'0';
ch=getchar();
}
return f==1?res:-res;
}
int n,m,dis[N],dep[N],val[N];
int nxt[M],to[M],head[N],w[M],ecnt=0;
inline void add(int x,int y,int z){ nxt[++ecnt]=head[x];head[x]=ecnt;to[ecnt]=y;w[ecnt]=z;}
int fa[N][25];
struct node{int u,v,lca,len;}p[N];
void dfs(int u,int fu){
fa[u][0]=fu;dep[u]=dep[fu]+1;
for(int e=head[u];e;e=nxt[e]){
int v=to[e];
if(v==fu) continue;
dis[v]=dis[u]+w[e];val[v]=w[e];
dfs(v, u);
}
}
inline int getlca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=19;i>=0;--i) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
if(x==y) return x;
for(int i=19;i>=0;--i){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i];y=fa[y][i];
}
}
return fa[x][0];
}
int maxn,num,s[N],del;
void Dfs(int u){
for(int e=head[u];e;e=nxt[e]){
int v=to[e];
if(v==fa[u][0]) continue;
Dfs(v);
s[u]+=s[v];
}
if(s[u]==num) del=max(del,val[u]);
}
inline bool check(int std){
num=0;del=0;
memset(s,0,sizeof(s));
for(int i=1;i<=m;++i){
if(p[i].len>std){
num++;
s[p[i].u]++;
s[p[i].v]++;
s[p[i].lca]-=2;
}
}
Dfs(1);
if(maxn-del<=std) return 1;
return 0;
}
int main(){
n=in;m=in;
int i,j,k,a,b,c;
for(i=1;i<n;++i){
a=in;b=in;c=in;
add(a,b,c);add(b,a,c);
}
dfs(1,0);
for(j=1;j<=19;++j)
for(i=1;i<=n;++i)
fa[i][j]=fa[fa[i][j-1]][j-1];
for(i=1;i<=m;++i){
p[i].u=in;p[i].v=in;
p[i].lca=getlca(p[i].u,p[i].v);
p[i].len=dis[p[i].u]+dis[p[i].v]-2*dis[p[i].lca];
maxn=max(maxn,p[i].len);
}
int l=0,r=maxn,ans=0;//
while(l<=r){
int mid=l+r>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans;
return 0;
}