NOIP2015 运输计划题解
思路:树上差分+lca+二分
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxn 300005
using namespace std;
struct node
{
int to,next,w;
}ed[maxn*2+5];
struct wa
{
int l;
int a;
int b;
int c;
}way[maxn];
bool flag;
int f[maxn][20],lg[maxn],head[maxn],cnt=0,m,n,a,b,c,num[maxn],sd[maxn],maxb,pas[maxn],ret=0,temp=0,ans,len[maxn];
void addnode(int u,int v,int worth)
{
cnt++;
ed[cnt].next = head[u];
ed[cnt].w = worth;
ed[cnt].to = v;
head[u]=cnt;
}
void dfs(int u,int fa,int wor)
{
len[u]=len[fa]+wor;
sd[u]=sd[fa]+1;
f[u][0]=fa;
for(int i=1;i<20;++i)
{
f[u][i]=f[f[u][i-1]][i-1];
}
for(int i=head[u];i;i=ed[i].next)
{
if(ed[i].to!=fa)
{
dfs(ed[i].to ,u,ed[i].w );
}
}
}
void dfs2(int s,int fa)
{
pas[s]=num[s];
for(int i=head[s];i;i=ed[i].next)
{
if(ed[i].to!=fa)
{
dfs2(ed[i].to,s);
if (pas[ed[i].to] == temp)
{
flag = true ; ret = max(ret ,ed[i].w);
}
pas[s]+=pas[ed[i].to];
}
}
}
bool ck(int t)
{
flag=false;
temp=0;
ret=0;
for (int i = 1;i<=n;++i) num[i] = 0;
for(int i=1;i<=m;i++)
{
if(way[i].l>t)
{
temp++;
num[way[i].a ]++;
num[way[i].b ]++;
num[way[i].c ]-=2;
}
}
if (!temp) return true;
dfs2(1,0);
if(!flag) return false;
if(maxb-ret<=t) return true;
return false;
}
int lca(int u,int v)
{
if(sd[u]<sd[v]) swap(u,v);
while(sd[u]>sd[v]) u=f[u][lg[sd[u]-sd[v]]];
if(u==v) return u;
for(int i=lg[sd[u]];i>=0;--i)
{
if(f[u][i]!=f[v][i])
{
u=f[u][i];
v=f[v][i];
}
}
return f[u][0];
}
inline int read()
{
char ch=getchar();
int s=0;
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9')
{
s=s*10+ch-'0';
ch=getchar();
}
return s;
}
int main()
{
n=read();
m=read();
lg[0]=-1;
for(int i=1;i<=n;++i)
{
lg[i]=lg[i>>1]+1;
}
for(int i=1;i<n;++i)
{
a=read();
b=read();
c=read();
addnode(a,b,c);
addnode(b,a,c);
}
dfs(1,0,0);
for(int i=1;i<=m;++i)
{
a=read();
b=read();
c=lca(a,b);
way[i].a =a;
way[i].b =b;
way[i].c =c;
way[i].l=len[a]+len[b]-2*len[c];
maxb=max(maxb,way[i].l);
}
int l=0,r=maxb+1;
while(l<=r)
{
int mid=(l+r)>>1;
if(ck(mid))
{
ans=mid;
r=mid-1;
}
else l=mid+1;
}
cout<<ans;
return 0;
}