【题解】noip2015 运输计划
noip2015 运输计划
题意
解法
我们考虑二分答案。我们二分操作后最长的长度为多少,然后看他能否办到。然后我们考虑m条路径中长度大于(要预处理长度)mid的路径,将它经过的路径标记起来,然后我们看是否有边被大于mid的所有边经过,然后再看最大值减去这条边的值是否小于等于mid就行了。
至于如何标记树上的边覆盖的边,树上差分一下就好了。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cctype>
#define INF 2139062143
#define MAX 0x7ffffffffffffff
#define del(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
template<typename T>
inline void read(T&x)
{
x=0;T k=1;char c=getchar();
while(!isdigit(c)){if(c=='-')k=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=k;
}
const int maxn=3e5+15;
int fir[maxn],nxt[maxn*2],wi[maxn*2],to[maxn*2],ecnt;
void add_edge(int u,int v,int w) {
nxt[++ecnt]=fir[u];fir[u]=ecnt;wi[ecnt]=w;to[ecnt]=v;
nxt[++ecnt]=fir[v];fir[v]=ecnt;wi[ecnt]=w;to[ecnt]=u;
}
int dep[maxn],fa[maxn],sz[maxn],son[maxn],top[maxn],dfn;
int tot[maxn];
void dfs1(int u,int f) {
fa[u]=f;sz[u]=1,dep[u]=dep[f]+1;son[u]=0;
for(int e=fir[u];e;e=nxt[e]) {
int v=to[e];
if(v==f) continue;
tot[v]=tot[u]+wi[e];
dfs1(v,u);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int topf) {
top[u]=topf;
if(son[u]) dfs2(son[u],topf);
for(int e=fir[u];e;e=nxt[e]) {
int v=to[e];
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
int LCA(int x,int y) {
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
return x;
}
int n,m;
struct node {
int u,v,len,lca;
}q[maxn];
int co[maxn];
void dfs(int u) {
for(int e=fir[u];e;e=nxt[e]) {
int v=to[e];
if(v==fa[u]) continue;
dfs(v);
co[u]+=co[v];
}
}
bool check(int sta) {
del(co,0);int cnt=0,maxx=0;
for(int i=1;i<=m;i++) {
if(q[i].len>sta) {
maxx=max(q[i].len,maxx);
++co[q[i].v],++co[q[i].u];
co[q[i].lca]-=2;
++cnt;
}
}
if(!cnt) return 1;
dfs(1);
for(int i=2;i<=n;i++) {
if(co[i]==cnt&&maxx-(tot[i]-tot[fa[i]])<=sta) return 1;
}
return 0;
}
int main()
{
read(n),read(m);
int u,v,w;
for(int i=1;i<n;i++) {
read(u),read(v),read(w);
add_edge(u,v,w);
}
dfs1(1,0);dfs2(1,1);
int l=0,r=0;
for(int i=1;i<=m;i++) {
read(q[i].u),read(q[i].v);
q[i].lca=LCA(q[i].u,q[i].v);
q[i].len=tot[q[i].u]+tot[q[i].v]-2*tot[q[i].lca];
r=max(r,q[i].len);
}
int ans;
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;
}

浙公网安备 33010602011771号