题目
首先我们二分一下答案。
然后我们用倍增让军队往上跳,最多先跳到根的子节点。
如果当前军队可以到达根节点,那么记录一下它的编号和它到达根节点后还可以走的时间。
并且我们记录根节点的叶子节点上到根节点后剩余时间最短的军队。
如果不可以到达根节点,那么在它跳到的节点设置检查点。
如果一个节点建立了检查点或者它的所有子树都设立了检查点,则说明以这个节点为根的子树已经被封死。记录根节点的所有子树中,未被封死的子树。
将我们已经记录好了的可以到根节点的军队按照剩余时间从大到小排序。
将未被封死的子树按照到子树到根节点的距离从大到小排序。
然后依次处理未被封死的子树要由哪支军队来管辖。
离根节点远的子树由剩余时间大的军队来管辖是没有问题的,不过更优的是由本来就在这棵子树上的军队来管辖。
所以我们先查看我们事先记录的(在子树中可以到达根节点,且到根节点后剩余时间最小的军队)是否被使用,如果被使用,再看当前没有被使用的军队里剩时间最大的可否到达这棵子树。

#include<bits/stdc++.h>
#define LL long long
#define pb push_back
#define P pair<int,int>
#define fir first
#define sec second
using namespace std;
namespace IO
{
    char ibuf[(1<<21)+1],*iS,*iT;
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;}
}
using namespace IO;
const int N=50007;
vector<P>E[N];
int pos[N],F[N][20],f[N],vis[N],used[N],r[N],n,m,cnt1,cnt2;
LL d[N][20];
struct node{int r,id;}a[N],b[N];
int operator<(node a,node b){return a.r>b.r;}
void dfs(int u,int fa,int dis)
{
    F[u][0]=fa,d[u][0]=dis;
    for(int i=1;i<=17;++i) F[u][i]=F[F[u][i-1]][i-1],d[u][i]=d[u][i-1]+d[F[u][i-1]][i-1];
    for(P p:E[u]) if(p.fir^fa) dfs(p.fir,u,p.sec);
}
int checkd(int u,int fa)
{
    int f1=1,f2=0;
    if(vis[u]) return 1;
    for(P p:E[u])
    {
        if(p.fir==fa) continue;
    f2=1;
    if(!checkd(p.fir,u))
    {
            f1=0;
            if(u==1) b[++cnt2]=(node){p.sec,p.fir};
            else return 0;
        }
    }
    return f1&f2;
}
int check(int T)
{
    cnt1=cnt2=0,memset(vis,0,sizeof vis),memset(f,0,sizeof f),memset(used,0,sizeof used);int i,j,u,s;
    for(i=1;i<=m;++i)
    {
    for(u=pos[i],s=0,j=17;~j;--j) if(F[u][j]>1&&d[u][j]+s<=T) s+=d[u][j],u=F[u][j];
    if(F[u][0]==1&&d[u][0]+s<=T)
    {
        a[++cnt1]=(node){T-s-d[u][0],i};
            if(!f[u]||a[cnt1].r<r[u]) r[u]=a[cnt1].r,f[u]=i;
        }
        else vis[u]=1;
    }
    if(checkd(1,0)) return 1;
    sort(a+1,a+1+cnt1),sort(b+1,b+1+cnt2),u=used[0]=1;
    for(i=1;i<=cnt2;++i)
    {
        if(!used[f[b[i].id]]){used[f[b[i].id]]=1;continue;}
        while(u<=cnt1&&(used[a[u].id]||a[u].r<b[i].r)) ++u;
        if(u>cnt1) return 0;
    used[a[u].id]=1;
    }
    return 1;
}
main()
{
    n=read();int i,u,v,w,l=0,r=2e9,ans=-1,mid;
    for(i=1;i<n;++i) u=read(),v=read(),w=read(),E[u].pb(P(v,w)),E[v].pb(P(u,w));
    dfs(1,0,0),m=read();
    for(i=1;i<=m;++i) pos[i]=read();
    while(l<=r) check(mid=l+r>>1)? ans=mid,r=mid-1:l=mid+1;
    return !printf("%d",ans);
}

Luogu P1084 [NOIP2012]疫情控制的更多相关文章

  1. Luogu 1084 NOIP2012 疫情控制 (二分,贪心,倍增)

    Luogu 1084 NOIP2012 疫情控制 (二分,贪心,倍增) Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是 ...

  2. [NOIP2012]疫情控制 贪心 二分

    题面:[NOIP2012]疫情控制 题解: 大体思路很好想,但是有个细节很难想QAQ 首先要求最大时间最小,这种一般都是二分,于是我们二分一个时间,得到一个log. 然后发现一个军队,越往上走肯定可以 ...

  3. NOIP2012 疫情控制 题解(LuoguP1084)

    NOIP2012 疫情控制 题解(LuoguP1084) 不难发现,如果一个点向上移动一定能控制更多的点,所以可以二分时间,判断是否可行. 但根节点不能不能控制,存在以当前时间可以走到根节点的点,可使 ...

  4. noip2012 疫情控制

    [问题描述] H国有n个城市,这n个城市用n-1条双向道路相互连通构成一棵树,1号城市是首都,也是树中的根节点. H国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子 ...

  5. NOIP2012疫情控制(二分答案+倍增+贪心)

    Description H国有n个城市,这n个城市用n-1条双向道路相互连通构成一棵树,1号城市是首都,也是树中的根节点. H国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境 ...

  6. [NOIP2012]疫情控制(二分答案+倍增+贪心)

    Description H国有n个城市,这n个城市用n-1条双向道路相互连通构成一棵树,1号城市是首都,也是树中的根节点. H国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境 ...

  7. [NOIp2012]疫情控制 题解

    好久没更,强迫自己写一篇. 神 tm 大预言家出的题 注意到如果 \(x\) 小时可以控制住疫情,则 \(\forall x'>x\) 必然也可以控制住疫情,显然答案具有单调性,可以二分答案. ...

  8. NOIP2012疫情控制(二分答案+树上贪心)

    H 国有n个城市,这 n个城市用n-1条双向道路相互连通构成一棵树,1号城市是首都,也是树中的根节点. H国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示 ...

  9. noip2012疫情控制 题解

    题目大意 给出一棵n个节点的树,根是1,要在除根节点以外的点建立检查点,使得从每条根到叶子的路径上都至少存在一个检查点.检查点由军队来建立.初始军队的位置是给定的,移动军队走一条边需要花费这条边的权值 ...

随机推荐

  1. The Preliminary Contest for ICPC Asia Shanghai 2019 B. Light bulbs

    题目:https://nanti.jisuanke.com/t/41399 思路:差分数组 区间内操作次数为奇数次则灯为打开状态 #include<bits/stdc++.h> using ...

  2. 织梦dedecms自定义表单导出到excel教程

    不写死任何字段,不写死任何东西,修改2个文件,让织梦自定义表单自由导出到Excel表格里. 添加教程 1.\dede\templets\diy_main.htm 找到 前台预览</a> 在 ...

  3. 8.django单独执行文件

    import os import django # 导入django os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'noju.settings')d ...

  4. Linux培训教程 Git在linux下的使用

       *初始化git仓库,使用gitinit命令 *添加文件到git仓库分两步: 1.使用git add filename ;可分多次使用,添加多个文件到暂存区 2.使用git commit -m “ ...

  5. 2019.9.23JAVA动手动脑

    1请看以下代码,你发现了有什么特殊之处吗? // MethodOverload.java// Using overloaded methods public class MethodOverload ...

  6. Spring Cloud云服务架构 - commonservice-config配置服务搭建

    1. 介绍 Spring Cloud Config为分布式系统中的外部配置提供服务器和客户端支持.使用Config Server,您可以在所有环境中管理应用程序的外部属性.客户端和服务器上的概念映射与 ...

  7. 深入浅出mysql笔记---1、mysql下载安装

    深入浅出mysql笔记---1.mysql下载安装 一.总结 一句话总结: linux下rpm安装即可 1.linux的wget命令作用? 下载文件的工具:比如wget http://cn.wordp ...

  8. Oracle JET 单页面应用程序Router 使用(上)

    单页面应用程序:使用一个进加载一次的网页,如果页面由于用户的交互而改变,则仅绘制更改的页面部分. 要创建单页面应用程序需要使用 oj.Router 的虚拟导航来支持,ojModule 用来响应页面的重 ...

  9. 一、基础篇--1.1Java基础-包装类的装箱和拆箱

    包装类:java是典型的面向对象编程,但是八种基本数据类型并不支持面向对象编程.基本类型的数据不具备对象的特性,没有属性和方法.沿用它们只是为了迎合人类根深蒂固的习惯,并的确能简单.有效地进行常规数据 ...

  10. inode节点号

    查看分区信息命令 df -Th 查看文件inode节点号 ls -i b.txt 查看系统中与b.txt 的inode节点号相同的所有文件,即硬链接 find  /  -inum  xxxx(b.tx ...