【NOIP2015提高组Day2T3】运输计划
前置思路
这个题目这里提供的解题思路就是 二分+LCA+树上边差分。
思路
大体上就是原来的边上差分模板,这里不在过多赘述。
while(m--){
cin>>f1>>f2;
f3=1;
c[f1]+=f3;
c[f2]+=f3;
c[lca(f1,f2)]-=f3*2;
}
主要就是判断这个答案是什么?
我们这里定义 d 表示最大完成时间,这里同边差分一样,我们直接计算得到 \(d=c_u+c_v-c_{lca(u,v)}\)。
然后我们就暴力去尝试,枚举每个航线,看这个时间是否在阈值之外,这样我们就考虑修改这个航线上面的地方,然后找到所有超过阈值的所有航线的交点,一定修改这里因为修改这里会让结果最小化。
可是,恭喜你——超时了!
超时了怎么办?
题目给了很明显的题目“最长的最小”显然二分答案。标程代码
恭喜你——AC了!
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
//#define int long long
int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch == '-') f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
void write(int x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9) write(x/10);
putchar(x%10+'0');
return ;
}
const int N=300005;
struct node{
int u,v,lca,d;
}a[N];
int n,m,f1,f2,f3,maxn,l,r,mid,ecnt,ect;
int dep[N],fa[N][20],c[N],d[N],dfn[N],b[N],h[N];
struct edge{
int v,p,w;
}e[N<<1];
void add(int u,int v,int w){
ect++;
e[ect]=edge{v,h[u],w};
h[u]=ect;
return ;
}
void dfs(int u,int f){
fa[u][0]=f;
ecnt++;
dfn[u]=ecnt;
for(int i=1;i<=19;++i) fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=h[u];i;i=e[i].p){
int v=e[i].v;
if(v==f) continue;
int w=e[i].w;
dep[v]=dep[u]+1;
c[v]=c[u]+w;
b[v]=w;
dfs(v,u);
}
return ;
}
int lca(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
int d=dep[u]-dep[v],k=0;
while(d!=0){
if(d&1) u=fa[u][k];
d>>=1;
k++;
}
if(u==v) return u;
for(int i=19;i>=0;i--){
if(fa[u][i]!=fa[v][i]){
u=fa[u][i];
v=fa[v][i];
}
}
return fa[u][0];
}
void tree_cha(int u,int fa){
for(int i=h[u];i;i=e[i].p){
int v=e[i].v;
if(v==fa) continue;
tree_cha(v,u);
d[u]+=d[v];
}
return ;
}
bool cheak(int kx){
int tot=0;
for(int i=1;i<=m;++i){
if(a[i].d>kx){
tot++;
d[a[i].u]++;
d[a[i].v]++;
d[a[i].lca]-=2;
}
}
tree_cha(1,1);
bool can=0;
for(int i=1;i<=n;++i){
if(d[i]==tot&&maxn<=kx+b[i]) can=1;
d[i]=0;
}
return can;
}
int main(){
// ios::sync_with_stdio(0);
// cin.tie(0);
// cout.tie(0);
// cin>>n>>m;
n=read();
m=read();
for(int i=1;i<n;++i){
// cin>>f1>>f2>>f3;
f1=read();
f2=read();
f3=read();
add(f1,f2,f3);
add(f2,f1,f3);
}
dfs(1,1);
for(int i=1;i<=m;++i){
// cin>>a[i].u>>a[i].v;
a[i].u=read();
a[i].v=read();
a[i].lca=lca(a[i].u,a[i].v);
a[i].d=c[a[i].u]+c[a[i].v]-2*c[a[i].lca];
maxn=max(maxn,a[i].d);
}
l=0;
r=maxn;
while(l<=r){
mid=(l+r)>>1;
if(cheak(mid)) r=mid-1;
else l=mid+1;
}
// cout<<l;
write(l);
return 0;
}
浙公网安备 33010602011771号