疫情控制
对于最值问题,在树上首先思考贪心和dp
我们发现,一个军队要移动,一定是往上移动到深度最小的位置,或者是绕过root到一个root的子节点
经过思考,正着做较难,但如果转为二分答案(因为答案有单调性),判定时我们有较好的贪心策略
在实现的时候细节较多,要自己调一下
将军队向上走的时候,用倍增,加上二分答案,复杂度两个log
#include<bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define SZ(x) ((int)x.size())
#define ALL(x) x.begin(),x.end()
#define U(i,u) for(register int i=head[u];i;i=nxt[i])
#define rep(i,a,b) for(register int i=(a);i<=(b);++i)
#define per(i,a,b) for(register int i=(a);i>=(b);--i)
using namespace std;
typedef long double ld;
typedef long long ll;
typedef unsigned int ui;
typedef pair<int,int> PII;
typedef vector<int> VI;
template<class T> inline void read(T &x){
x=0;char c=getchar();int f=1;
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=f;
}
template<class T> inline void cmin(T &x, T y){x=x<y?x:y;}
template<class T> inline void cmax(T &x, T y){x=x>y?x:y;}
const int N=100010;
const int LOG=21;
int n,m,head[N],nxt[N<<1],v[N<<1],cnt,pos[N],anc[N][LOG],dep[N],len,tot,vis[N];
int re[N],mix[N],pix[N];
int whi[N];
ll w[N<<1],dis[N][LOG],mx;
struct node{
int b,id;ll c;
}le[N],ne[N];
void add(int x,int y,ll z){nxt[++cnt]=head[x];head[x]=cnt;v[cnt]=y;w[cnt]=z;}
void dfs(int now,int fa,int de,ll fr,int wi){
if(fa==1)whi[now]=now;else whi[now]=wi;
dis[now][0]=fr;anc[now][0]=fa;dep[now]=de;U(i,now){
if(v[i]==fa)continue;
if(fa==1)dfs(v[i],now,de+1,w[i],now);
else dfs(v[i],now,de+1,w[i],wi);
}
}
void init(){
dfs(1,0,0,0,0);
rep(j,1,19)rep(i,1,n){
anc[i][j]=anc[anc[i][j-1]][j-1];
if(anc[i][j])dis[i][j]=dis[anc[i][j-1]][j-1]+dis[i][j-1];
}
}
void sup(int x,ll li,int id){
int tmp=whi[x];per(j,19,0){if(anc[x][j]>0)if(dis[x][j]<=li)li-=dis[x][j],x=anc[x][j];}
if(x==1){
le[++len].b=x,le[len].c=li,le[len].id=id;
if(li<mix[tmp])pix[tmp]=le[len].id,mix[tmp]=li;
}
else{vis[x]=1;}
}
void bl(int now,int fa){
bool flag=0,hs=0;
U(i,now){
if(fa==v[i])continue;hs=1;
bl(v[i],now);
if(vis[v[i]]==0)flag=1;
}
if(flag==0&&hs){
vis[now]=1;
}
}
bool cmp(node aa,node bb){
return aa.c<bb.c;
}
bool check(ll li){
memset(vis,0,sizeof(vis));
memset(mix,0x3f,sizeof(mix));
memset(re,0,sizeof(re));
tot=0;len=0;rep(i,1,m){sup(pos[i],li,i);}
bl(1,0);U(i,1){
if(!vis[v[i]]){
if(mix[v[i]]<0x3f3f3f3f&&mix[v[i]]<w[i])re[pix[v[i]]]=1;
else ne[++tot].b=v[i],ne[tot].c=w[i];
}
}
sort(le+1,le+len+1,cmp);
sort(ne+1,ne+tot+1,cmp);
int j=1;
rep(i,1,tot){
while(re[le[j].id])++j;
while(le[j].c<ne[i].c&&j<=len)++j;
if(j>len)return 0;
++j;
}
return 1;
}
int main(){
read(n);rep(i,1,n-1){int x,y;ll z;read(x);read(y);read(z);add(x,y,z);add(y,x,z);mx+=z;}
read(m);rep(i,1,m)read(pos[i]);init();
ll l=0,r=mx;
while(r-l>=3){
ll mid=(l+r)>>1;
if(check(mid))r=mid;
else l=mid+1;
}
for(ll i=l;i<=r;i++){if(check(i)){
printf("%lld
",i);
return 0;
}}
printf("-1
");
return 0;
}
/*
8
4 1 2
3 4 8
2 1 7
7 8 8
8 4 3
6 1 7
4 5 1
7
6 7 5 6 6 6 6
ans=10;
*/