疫情控制sol
阿新 • • 發佈:2020-07-25
疫情控制
對於最值問題,在樹上首先思考貪心和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\n",i); return 0; }} printf("-1\n"); 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; */