首页 > 其他分享 >疫情控制

疫情控制

时间:2023-10-10 13:22:36浏览次数:41  
标签:控制 ver 疫情 army int mid cin ##

P1084 [NOIP2012 提高组] 疫情控制

我们先考虑允许走到根的做法。

首先就是二分答案,然后每个军队尽可能往上跳跃,可以用倍增。(往下不优),最后检查是不是满足要求就行了。

不允许到根,所以可能有的军队需要支援其他地方。

我们先把不能到达根的点先原地驻扎。

此时,我们发现对于一个军队,如果它是剩余时间最少的点,且不能走到根再回来,那么我们选择原地驻扎。

  1. 如果用本来的点驻扎,那不如剩余时间少的点,可以把剩余时间多的用于支援。
  2. 如果是外来的点,那么这个点如果能到其他地方,那么说明那个地方的距离肯定小于原先位置到根的距离,那让外来点到这个点到的其他点上。

除此之外,其他点都可以被派遣(如果一个点还是回去,反正它可以去了再回,其实是等价的),那么每个其他点到根之后的剩余时间被求出,而且支援的点的距离也是有的,所以可以贪心的将剩余时间少的军队支援距离短的点。

复杂度 \(O(n\log n)\)。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define Ed for(int i=h[x];~i;i=ne[i])
#define Ls(i,l,r) for(int i=l,i##end=r;i<i##end;++i)
#define Rs(i,l,r) for(int i=l,i##end=r;i>i##end;--i)
#define Le(i,l,r) for(int i=l,i##end=r;i<=i##end;++i)
#define Re(i,l,r) for(int i=l,i##end=r;i>=i##end;--i)
#define L(i,l) for(int i=0,i##end=l;i<i##end;++i)
#define E(i,l) for(int i=1,i##end=l;i<=i##end;++i)
#define W(t) while(t--)
#define Wh while
typedef long long ll;
const int N=50010,K=16,M=2*N;
const ll INF=5e13;
struct Army{
    int ver;
    ll rest;
    bool is_del;
}army[N];
ll d[N];
bool g[N],st[N];
int n,m,f[N][K],q[N],p[N];
int h[N],e[M],ne[M],idx,w[M];//don't forget memset h!
void add(int a,int b,int c){
    w[idx]=c,e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void init(int x,int fa,ll dis){
    d[x]=dis;
    Ed{
        int j=e[i];
        if(j==fa)continue;
        f[j][0]=x;
        E(i, K-1)f[j][i]=f[f[j][i-1]][i-1];
        init(j,x,dis+w[i]);
    }
}
#define leaf(x) (!~ne[h[x]])
void dfs(int x,int fa,bool hv_army){
    hv_army|=st[x];
    if(leaf(x))g[x]=hv_army;
    else{
        g[x]=1;
        Ed{
            int j=e[i];
            if(j==fa)continue;
            dfs(j,x,hv_army);
            if(!g[j])g[x]=0;
        }
    }
}
bool check(ll mid){
    memset(st,0,sizeof st);
    memset(g,0,sizeof g);
    int cnt=0;
    E(i, m){
        int j=q[i];
        Re(k, K-1, 0)
            if(f[j][k]>1&&d[q[i]]-d[f[j][k]]<=mid)j=f[j][k];
        if(d[q[i]]>mid)st[j]=1;
        else army[++cnt]={j,mid-(d[q[i]]-d[j]),0};
    }
    dfs(1,-1,0);
    memset(p,-1,sizeof p);
    E(i, cnt){
        int ver=army[i].ver;
        if(!~p[ver]||army[p[ver]].rest>army[i].rest)p[ver]=i;
    }
    int x=1;
    Ed{
        int j=e[i];
        if(!g[j]){
            int k=p[j];
            if(~k&&army[k].rest<d[army[k].ver]*2){
                g[j]=1;
                army[k].is_del=1;
            }
        }
    }
    int ncnt=0,gcnt=0;
    E(i, cnt)
        if(!army[i].is_del)army[++ncnt]=army[i];
    Ed{
        int j=e[i];
        if(!g[j])p[++gcnt]=j;
    }
    sort(army+1,army+ncnt+1,[&](Army& x,Army& y){
        return x.rest-d[x.ver]<y.rest-d[y.ver];
    });
    sort(p+1,p+1+gcnt,[&](int x,int y){
        return d[x]<d[y];
    });
    int k=1;
    for(int i=1;i<=ncnt&&k<=gcnt;i++)
        if(army[i].rest-d[army[i].ver]>=d[p[k]])k++;
    return k==gcnt+1;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    #endif
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    memset(h,-1,sizeof h);
    E(i, n-1){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c),add(b,a,c);
    }
    init(1,-1,0);
    check(INF);
    cin>>m;
    E(i, m)cin>>q[i];
    ll l=0,r=INF;
    Wh(l<r){
        ll mid=l+r>>1;
        if(check(mid))r=mid;
        else l=mid+1;
    }
    cout<<(r==INF?-1:r);
    return 0;
}

标签:控制,ver,疫情,army,int,mid,cin,##
From: https://www.cnblogs.com/wscqwq/p/17754429.html

相关文章

  • 每日一题:通过css变量来控制主题
    1、定义不同主题颜色:root{--theme-color:blue;--font-size:18px;;}html[theme="dark"]{--theme-color:#000;2、通过切换html自定义属性来控制主题<!DOCTYPEhtml><htmllang="en"><head><met......
  • 智慧锅炉:工业动力锅炉2D组态控制系统
    前言锅炉是化工、炼油、发电等工业生产中必不可少的动力设备。随着工业生产规模的不断扩大,生产设备的不断创新,作为全厂动力和热源的锅炉,亦向着大容量、高参数、高效率发展。由于我国锅炉自动化控制程度不高,目前锅炉主要以人工巡检为主。但是锅炉设备位置分散,若巡检和维修都需要维......
  • 基于工业5G网关的工业机器人监测控制方案
    随着智能制造、自动化生产的发展进步,工业机器人的身影越来越多地出现在工厂现场,成为新型无人化、智能化生产制造的中坚力量。工业机器人的运行伴生着海量的数据采集、传输、分析和反馈执行,因此也需要高速、低延迟的5G网络,支撑工业机器人的高效、可靠运转。本篇就为大家介绍基于工......
  • 封装中内置了开关控制器的LTM4662EY/LTM4680EY/LTM4686IV DC/DC直流转换器
    1、LTM4662EY 双通道15ADC/DCμModule稳压器LTM4662是一款完整的双通道15A输出开关模式DC/DC电源。封装中内置了开关控制器、功率FET、电感器和所有的支持组件。该器件可在一个4.5V至20V的输入电压范围内工作,支持两个输出电压范围均为0.6V至5.5V(由外部电阻器设......
  • Java-流程控制
    Java流程控制是Java编程语言中非常重要的一个部分,它允许程序员根据程序执行的顺序来控制代码的执行流程。在Java中,流程控制主要包括条件语句、循环语句和选择语句等。一、条件语句条件语句用于根据条件的真假来执行不同的代码块。Java中主要有两种条件语句:if-else语句和switch语......
  • 7、Python语法入门之流程控制
    7、Python语法入门之流程控制转载: 7、Python语法入门之流程控制-知乎(zhihu.com)目录:引子分支结构什么是分支结构为什么要用分支结构如何使用分支结构if语法if应用案例循环结构什么是循环结构为什么要用循环结构如何使用循环结构while循环语......
  • 安卓开发图片动态操作,利用SeekBar控制属性示例
    屏幕大小适配演示,综合练习。功能为,用一个滑块来控制图片的旋转,用一个滑块来控制图片大小,核心语法思路,控制图片的大小,mImageView.setLayoutParams(newLinearLayout.LayoutParams(newWidth,newHeight));但是这儿二个属性要提前配置,并且图片大不能超出屏幕,所以先计算屏幕大小,pr......
  • Service mesh 学习08 控制平面和数据平面
    一、技术选型二、数据平面Envoy......
  • [异常处理]rabbitMQ 消费端异常进入死循环-消费消息时候抛出错误,控制台一直刷
    消费端一直在循环消费消>报错->消费.问题点也能想的来,因为默认是自动应答,异常了相当于是没有应答,然后就一直异常重新抛回队列进行投递.解决方案:第一种方法:对可能发生异常的部分try、catch;只要事先将问题catch住,就证明消费端已经将该问题消费掉,然后该消息就不存在于队列中......
  • Java流程控制10道题_上机
    Java流程控制10道题计算出1-100之间所有不能被3整除的整数的和大于(或等于)2000的数字。packageday01;publicclassLab01{publicstaticvoidmain(String[]args){//计算出1-100之间所有不能被3整除的整数的和大于(或等于)2000的数字。intsum......