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

#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. 记录下:nth-child在table中遇到的问题~(已解决)

    首先做了一个表格,如下: <!DOCTYPE html> <html> <head> <title></title> <style t ...

  2. 兄弟连教育分享-SQL性能优化十条经验

    1.查询的模糊匹配 尽量避免在一个复杂查询里面使用 LIKE '%parm1%'——红色标识位置的百分号会导致相关列的索引无法使用,最好不要用. 兄弟连教育分享-SQL性能优化十条经验 解决办法: 其 ...

  3. #333 Div2 Problem B Approximating a Constant Range (尺取 && RMQ || 尺取 && multiset)

    题目链接:http://codeforces.com/contest/602/problem/B 题意 :给出一个含有 n 个数的区间,要求找出一个最大的连续子区间使得这个子区间的最大值和最小值的差值 ...

  4. (58)PHP开发

    LAMP 0.使用include和require命令来包含外部PHP文件. 使用include_once命令,但是include和include_once命令相比的不足就是这两个命令并不关心请求的文件 ...

  5. 大哥带的MSsql注入(SQL Server)--预习

    ①判断数据库类型and exists (select * from sysobjects)--返回正常为mssql(也名sql server)and exists (select count(*) f ...

  6. 【每日一包0002】array-first

    github地址:https://github.com/ABCDdouyae... array-first 获取数组的第一项或者前几项 文档地址:https://www.npmjs.com/packa ...

  7. jdbcType="DATE"和jdbcType=" TIMESTAMP"的区别

    原文: https://www.cnblogs.com/fswhq/p/jdbcType.html 当传入null值时,jdbcType 会防止null空指针异常报错 Mybatis 中jdbcTyp ...

  8. jQuery.parseJSON()

    https://api.jquery.com/jQuery.parseJSON/ https://api.jquery.com/category/deprecated/deprecated-3.0/ ...

  9. C# 读写App.config 配置文件

    先要添加引用:System.Configuration //using System.Configuration; if (System.IO.File.Exists(AppDomain.Curren ...

  10. serial redirection

    int setOption(int fd,int nSpeed, int nBits, char mode,char nEvent, int nStop) { struct termios newti ...