运输计划
二分答案的做法放到树上呢
考虑线性数据上二分的完整做法
预处理每一条链的length,二分答案,放到check函数里搞
没问题
LCA求出每条链的length,还是二分,check函数换成树上差分
最后发现正解只要一句话:
求链长+二分
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=3e5+10;
struct edge{
int next,to,dis;
}e[2*maxn],q[2*maxn];
struct length{
int len,lca,u,v;
}len[maxn];
int head[maxn],cnt,headq[maxn],dis[maxn],maxlen,n,m,a[maxn],ans,s[maxn],num,ret,f[maxn];
bool vis[maxn];
inline int readn()
{
int x=0;
char ch=getchar();
while(ch>'9'||ch<'0')
ch=getchar();
while(ch>='0'&&ch<='9')
{
x=(x<<3)+(x<<1)+(ch^'0');
ch=getchar();
}
return x;
}
inline void add_edge(int x,int y,int d)
{
e[++cnt].next=head[x];
e[cnt].to=y;
e[cnt].dis=d;
head[x]=cnt;
}
inline void add_que(int x,int y)
{
q[++cnt].next=headq[x];
q[cnt].to=y;
headq[x]=cnt;
}
int find(int x)
{
return f[x]==x?f[x]:f[x]=find(f[x]);
}
void dfs(int u,int pre)
{
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(v==pre)
continue;
dfs(v,u);
s[u]+=s[v];
}
if(s[u]==num&&a[u]>ret)
ret=a[u];
}
inline bool check(int x)
{
memset(s,0,sizeof(s));
num=ret=0;
for(int i=1;i<=m;i++)
if(len[i].len>x)
{
s[len[i].u]++;
s[len[i].v]++;
s[len[i].lca]-=2;
num++;
}
dfs(1,0);
if(maxlen-ret>x)
return 0;
return 1;
}
void tarjan(int u,int pre)
{
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if(v==pre)
continue;
dis[v]=dis[u]+e[i].dis;
tarjan(v,u);
a[v]=e[i].dis;
int f1=find(v);
int f2=find(u);
if(f1!=f2)
f[f1]=find(f2);
vis[v]=1;
}
for(int i=headq[u];i;i=q[i].next)
if(vis[q[i].to])
{
int p=(i+1)>>1;
len[p].lca=find(q[i].to);
len[p].len=dis[u]+dis[q[i].to]-2*dis[len[p].lca];
maxlen=max(maxlen,len[p].len);
}
}
int main()
{
n=readn(),m=readn();
for(int i=1;i<n;i++)
{
int ai=readn(),bi=readn(),ti=readn();
add_edge(ai,bi,ti);
add_edge(bi,ai,ti);
}
for(int i=1;i<=n;i++)
f[i]=i;
cnt=0;
for(int i=1;i<=m;i++)
{
int x=readn(),y=readn();
len[i].u=x;
len[i].v=y;
add_que(x,y);
add_que(y,x);
}
tarjan(1,0);
int l=0,r=maxlen,mid;
while(l<=r)
{
mid=(l+r)>>1;
if(check(mid))
{
r=mid-1;
ans=mid;
}
else
l=mid+1;
}
printf("%d\n",ans);
return 0;
}

浙公网安备 33010602011771号