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

#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. 【NOIP2016提高A组模拟8.19】(雅礼联考day2)总结

    第一题又有gcd,又有xor,本来想直接弃疗,不过后来想到了个水法: 当两个相邻的数满足条件时,那么他们的倍数也可能满足条件.然后没打,只打了个暴力. 正解就是各种结论,各种定理搞搞. 第二题,想都不 ...

  2. 原生js数组排序(封装方法)

    //两值互换 function Sort(arr, index){ //参数arr代表数组,index代表数组元素下标 arr[index] += arr[index + 1];  //a+=b; a ...

  3. MySQL错误日志显示(Got an error reading communication packets)的问题

    错误显示: 2019-05-28T12:54:08.267934+08:00 820396 [Note] Aborted connection 820396 to db: 'Databaseplatf ...

  4. 15. ClustrixDB 管理数据分布

    本节使用的关键术语: Relation — ClustrixDB中的每个表都被称为“关系”. Representation — 在ClustrixDB中,每个索引都称为一个“Representatio ...

  5. 游标定位:Cursor类

    关于 Cursor Cursor 是每行的集合. 使用 moveToFirst() 定位第一行. 你必须知道每一列的名称. 你必须知道每一列的数据类型. Cursor 是一个随机的数据源. 所有的数据 ...

  6. HDU 2612 Find a way(双向bfs)

    题目代号:HDU 2612 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2612 Find a way Time Limit: 3000/1000 M ...

  7. 苹果cms如何添加播放器预加载和缓冲广告

    1,来到系统后台>>系统>>播放器参数设置  可以看到添加预加载和缓冲广告的输入框.文件格式为html 自己写一个html的网页上传到网站进行调用即可.链接前面不要加http或 ...

  8. 向android模拟器打电话发短信的简单方法

    在开发android应用程序时,有时候需要测试一下向android手机拨打电话发送短信时该应用程序的反应.譬如编写一个广播接收器,来提示用户有短信收到或者处理短信,就需要向该手机发送短信来进行测试.这 ...

  9. 看完你也想编写自己的 react 插件

    副标题----为什么我要写这个 react 插件 图片懒加载是项目中常用的功能,然而现有 react 懒加载组件库,用着都不是很爽了 ?.概括一下有如下几点: 没有只针对 image 懒加载组件.多数 ...

  10. phpmyadmin普通用户使用配置

    正常情况需求是,普通用户可以管理特定的数据库,可能也需要能新建数据库,配置如下: 1.添加用户,phpmyadmin和应用访问,所以主机设置127.0.0.1访问即可 2.如果只管理一个数据,可以选择 ...