• 疫情控制sol


    疫情控制
    对于最值问题,在树上首先思考贪心和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;
    */
    
  • 相关阅读:
    2020-09-24 刷题记录
    Codeforces Round #672 (Div. 2) A
    力扣部分刷题记录
    CF 1500-1800训练 A
    AtCoder Beginner Contest 179
    Educational Codeforces Round 95 (Rated for Div. 2) A
    AtCoder Beginner Contest 178 A
    springboot-------整合mybatis-plus
    机器学习入门--------numpy学习
    机器学习入门--------matplotlib学习
  • 原文地址:https://www.cnblogs.com/hangzz/p/13377605.html
Copyright © 2020-2023  润新知