//VFK出的题目,还是比较有水平的,倒是不卡常数
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 300000 + 5;
const int INF = 0x7f7f7f7f;
int fst[MAXN],next[MAXN<<1],len[MAXN<<1],to[MAXN<<1],ec=0;
inline void add(int u,int v,int w)
{
to[++ec]=v;
len[ec]=w;
next[ec]=fst[u];
fst[u]=ec;
}
int son[MAXN],size[MAXN],fa[MAXN],dep[MAXN],w[MAXN];
int dfn[MAXN],top[MAXN],s[MAXN],dfs_clock=0;
void dfs()
{
int cur[MAXN];
int tmp[MAXN],roof=0;//stack;
memcpy(cur,fst,sizeof(fst));
dep[1]=1;size[1]=1;son[1]=0;fa[1]=0;w[1]=0;
tmp[roof++]=1;
while(roof)
{
int u=tmp[roof-1];
if(cur[u])
{
int &e=cur[u];
int v=to[e];
if(v!=fa[u])
{
w[v]=len[e];
dep[v]=dep[u]+1;
fa[v]=u;
tmp[roof++]=v;
size[v]=1;
son[v]=0;
}
e=next[e];
}
else
{
for(register int i=fst[u];i;i=next[i])
{
int v=to[i];
if(v!=fa[u])
{
size[u]+=size[v];
if(size[son[u]]<size[v])son[u]=v;
}
}
roof--;
}
}
if(roof!=0)printf("error\n");
bool vis[MAXN];
memset(vis,0,sizeof(vis));
memcpy(cur,fst,sizeof(fst));
dfs_clock=0;
dfn[1]=++dfs_clock;
s[dfs_clock]=s[dfs_clock-1]+w[1];
top[1]=1;
tmp[roof++]=1;
vis[1]=true;
while(roof)
{
int u=tmp[roof-1];
if(son[u] && !vis[son[u]])
{
int v=son[u];
tmp[roof++]=v;
dfn[v]=++dfs_clock;
s[dfs_clock]=s[dfs_clock-1]+w[v];
top[v]=top[u];
vis[v]=true;
}
else if(cur[u])
{
int v=to[cur[u]];
if(!vis[v])//v!=fa[u]
{
tmp[roof++]=v;
vis[v]=true;
dfn[v]=++dfs_clock;
s[dfs_clock]=s[dfs_clock-1]+w[v];
top[v]=v;
}
cur[u]=next[cur[u]];
}
else roof--;
}
}
inline int road(int l,int r){return s[r]-s[l-1];}
int path(int u,int v)
{
if(u==v)return 0;
int ans=0;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])swap(u,v);
ans+=road(dfn[top[u]],dfn[u]);
u=fa[top[u]];
}
if(dep[u]>dep[v])swap(u,v);
ans+=road(dfn[son[u]],dfn[v]);///son u
return ans;
}
int n,m;
int in()
{
int c=getchar(),x=0;
while(c<'0'||c>'9')c=getchar();
while(c<='9'&&c>='0')
{
x=x*10+c-'0';
c=getchar();
}
return x;
}
struct plan{int u,v,w;}p[MAXN];
bool cmp(plan a,plan b){return a.w>b.w;}
int delta[MAXN];
inline void update(int l,int r)
{
delta[l]++;
delta[r+1]--;
}
void modify(int u,int v)
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])swap(u,v);
update(dfn[top[u]],dfn[u]);
u=fa[top[u]];
}
if(dep[u]>dep[v])swap(u,v);
update(dfn[son[u]],dfn[v]);son u
}
bool check(int x)
{
memset(delta,0,sizeof(delta));
int cnt_p=0,expt=0;
for(register int i=1;i<=m;i++)
{
if(p[i].w<=x)break;
cnt_p++;
expt=max(expt,p[i].w-x);
modify(p[i].u,p[i].v);
}
int cnt_e=0,mxp=0;
for(register int i=1;i<=n;i++)//i==dfn[u]
{
cnt_e+=delta[i];
if(cnt_e==cnt_p)mxp=max(mxp,road(i,i));
}
return mxp>=expt;
}
int main()
{
n=in();
m=in();
for(register int i=1;i<=n-1;i++)
{
int a=in(),b=in(),t=in();
add(a,b,t);
add(b,a,t);
}
dfs();
int l=0,r=0;
for(register int i=1;i<=m;i++)
{
p[i].u=in();
p[i].v=in();
p[i].w=path(p[i].u,p[i].v);
r=max(r,p[i].w);
}
sort(p+1,p+1+m,cmp);
int ans=0;
//printf("r=%d\n",r);
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid))
{
r=mid-1;
ans=mid;
}
else l=mid+1;
}
printf("%d\n",ans);
return 0;
}
NOIP2015 运输计划 树链剖分 差分 二分
最新推荐文章于 2019-09-21 14:41:35 发布