zoukankan      html  css  js  c++  java
  • 疫情控制

    题面

    一个军队越往上走他所管的叶子结点就越多,并且时间越多就越能够满足条件。

    于是考虑对于每个军队都先尽量往上跳(先不到根),对于一些有能力到根的把它们到达根之后剩余的时间和现在的位置记录下来(它们可以帮助堵住其他叶子节点),不然的话就让他原地驻扎。

    从根的儿子遍历,看这个儿子是否需要驻扎军队,对于需要驻扎的记录下来。

    对于一开始记录的军队,如果它们现在的位置需要军队并且它们到达根之后不能回来就原地驻扎就好,不这样的话他就只能去一些到根的距离小于现在位置到根的距离的地方,而这个位置就需要剩余时间比他多的军队来(排了序),而他能干的比他剩余时间多的都能干。

    现在再找出可以移动的军队的剩余时间和需要军队的根的儿子到根的距离,对两者排序,一一匹配。

    第二个不错

    倍增的时候注意先加值,再跳

    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define ll long long
    const int maxn=50005;
    int n,m,fa[maxn][25];
    ll l,r,ans=-1,sum[maxn][25];
    int cnt,head[maxn];
    int timer,safe[maxn];
    bool need[maxn];
    struct edge{
        int x,y,next;
        ll val;
    }e[maxn<<1];
    struct node{
        ll rest;int id;
        bool operator < (const node a) const {return a.rest>rest;}
    };
    vector<node> cx;//能到根的军队 
    vector<int> a;//军队初始位置 
    vector<int> go,want;//军队,根的儿子 
    
    template<class T>inline void read(T &x){
        x=0;int f=0;char ch=getchar();
        while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        x= f ? -x : x ;
    }
    
    void add(int x,int y,ll val){
        e[++cnt]=(edge){x,y,head[x],val};
        head[x]=cnt;
    }
    
    void dfs(int x){
        for(int i=1;i<=20;i++){
            fa[x][i]=fa[fa[x][i-1]][i-1];
            sum[x][i]=sum[x][i-1]+sum[fa[x][i-1]][i-1];
        }
        for(int i=head[x];i;i=e[i].next){
            int y=e[i].y;
            if(y==fa[x][0]) continue;
            fa[y][0]=x;
            sum[y][0]=e[i].val;
            dfs(y);
        }
    }
    
    void get(int x,ll rest){
        for(int i=20;~i;i--)
         if(fa[x][i]&&fa[x][i]!=1&&sum[x][i]<=rest){
              rest-=sum[x][i];
              x=fa[x][i];
         }
        if(fa[x][0]==1&&rest>=sum[x][0])
            cx.push_back((node){rest-sum[x][0],x});
        else safe[x]=timer;
    }
    
    bool find(int x){
        bool opt=true;//是否是边境。
        if(safe[x]==timer) return false;
        for(int i=head[x];i;i=e[i].next){
            int y=e[i].y;
            if(e[i].y==fa[x][0]) continue;
            opt=false;
            if(find(y)) return true;
        }
        return opt;
    }
    
    bool make_plan(){
        sort(want.begin(),want.end());
        unsigned int i=0,j=0;
        while(i<go.size()&&j<want.size()){
            if(go[i]>=want[j]) i++,j++;
            else i++;
        }
        return j==want.size();
    }
    
    bool check(ll tot){
        ++timer;
        cx.clear();
        go.clear();
        want.clear();
        for(unsigned int i=0;i<a.size();i++) get(a[i],tot);
        for(int i=head[1];i;i=e[i].next) need[e[i].y]=find(e[i].y);
        sort(cx.begin(),cx.end());
        for(unsigned int i=0;i<cx.size();i++)
         if(need[cx[i].id]&&sum[cx[i].id][0]>cx[i].rest)
              need[cx[i].id]=false;
         else go.push_back(cx[i].rest);
        for(int i=head[1];i;i=e[i].next)
         if(need[e[i].y]) want.push_back(sum[e[i].y][0]);
        return make_plan();
    }
    
    int main(){
        read(n);
        for(int i=1;i<n;i++){
            int x,y;ll val;
            read(x);read(y);read(val);
            add(x,y,val);
            add(y,x,val);
            r+=val;
        }
        read(m);
        for(int i=1;i<=m;i++){
            int x;read(x);
            a.push_back(x);
        }
        dfs(1);
        while(l<=r){
            ll mid=(l+r)>>1;
            if(check(mid)) ans=mid,r=mid-1;
            else l=mid+1;
        }
        printf("%lld",ans);
    }
    /*
    10
    2 1 3
    2 3 4
    1 4 7
    5 1 9
    6 1 2
    4 7 9
    7 8 8
    9 8 8
    1 10 2
    5
    2 8 5 4 2 
    */
    疫情控制
  • 相关阅读:
    head命令
    less命令
    解决get方法传递URL参数中文乱码问题
    The method convert(String) of type DateConverter must override a superclass method
    Tomcat Can't load AMD 64-bit .dll on a IA 32
    聚合函数查询 group by having
    string[] 清理重复+反转显示
    C# GetValueList 获得字符串中开始和结束字符串中间得值列表
    C# GetValue 正则获取开始结束代码
    string [] 去除重复字符两个方法
  • 原文地址:https://www.cnblogs.com/sto324/p/11580553.html
Copyright © 2011-2022 走看看