【二分+贪心+倍增】【NOIP2012】疫情控制

Description

H国有n个城市,这n个城市用n-1条双向道路相互连通构成一棵树,1号城市是首都,也是树中的根节点。 H国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是,首都是不能建立检查点的。 现在,在H国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等于道路的长度(单位:小时)。 请问最少需要多少个小时才能控制疫情。注意:不同的军队可以同时移动。

Input Format

第一行一个整数n,表示城市个数。 接下来的n-1行,每行3个整数,u、v、w,每两个整数之间用一个空格隔开,表示从城市u到城市v有一条长为w的道路。数据保证输入的是一棵树,且根节点编号为1。 接下来一行一个整数m,表示军队个数。 接下来一行m个整数,每两个整数之间用一个空格隔开,分别表示这m个军队所驻扎的城市的编号。

Output Format

共一行,包含一个整数,表示控制疫情所需要的最少时间。如果无法控制疫情则输出-1。

Sample Input

4
1 2 1
1 3 2
3 4 3
2
2 2 

Sample Output

3

Hint

保证军队不会驻扎在首都。

对于20%的数据,2≤ n≤ 10;

对于40%的数据,2 ≤n≤50, 0< w< 10^5;

对于60%的数据,2 ≤ n≤1000, 0< w <10^6;

对于80%的数据,2 ≤ n≤10,000;

对于100%的数据,2≤m≤n≤50,000,0 < w <10^9。

Solution

因为军队同时进行,且边有权值,
每支军队走完一条边剩下的时间不同,
所以最少时间一定是最后一个军队的停下的时间。
很显然可以二分答案。
验证答案时,要用到贪心的思想,
首先对于每支军队,向上走能控制的点就越多,
所以每支军队都应该向上走,
不能走到根节点的军队,就驻扎在停下来的点,
并做上标记,最后计算没被控制的子树到达根节点的距离,
对于能走到根节点的点,记录每支军队的剩余时间,我们考虑是否走到其他子树,
把可以走到根节点的军队的剩余时间以及没被控制的子树到达根节点的距离从小到大排序
然后贪心,剩余时间少的军队走距离根节点距离小的子树,
对于能走到根节点无法回到原子树的军队,我们选择留在原子树,
因为如果选择其他子树,说明其他子树距离根节点的距离小于原子树到达根节点距离,
所以军队选择其他子树,并不比留在原子树优。

#include<cstdio>
#include<cstring>
#include<algorithm>

int n,m;
int num,head[50005],army[50005],f[50005][20];
long long dis[50005][20],l,r,mid,ans=0;
bool se[50005];

struct node
{
    int pos,dis;
}A[50005],C[50005];

struct edge
{
    int to,next,dis;
}e[100005];

void add(int x,int y,int z)
{
    e[++num].next=head[x];
    e[num].to=y;
    e[num].dis=z;
    head[x]=num;
}

bool cmp(node a,node b)
{
    return a.dis<b.dis;
}

void dfs(int x,int fa)
{
    f[x][0]=fa;
    for (int i=1;i<17;i++)
    {
        f[x][i]=f[f[x][i-1]][i-1];
        dis[x][i]=dis[x][i-1]+dis[f[x][i-1]][i-1];
    }
    for (int i=head[x];i;i=e[i].next)
    {
        int v=e[i].to;
        if (v==fa) continue;
        dis[v][0]=e[i].dis;
        dfs(v,x);
    }
}

int up(int x,long long &dist)
{
    for (int i=16;i>=0;i--)
        if (f[x][i]>1&&dist+dis[x][i]<=mid) dist+=dis[x][i],x=f[x][i];
    return x;
}

bool go(int x,int fa)
{
    if (se[x]) return 1;
    int ned=0;
    for (int i=head[x];i&&ned<3;i=e[i].next) ned++;
    if (ned==1&&e[head[x]].to==fa) return se[x]=0;
    for (int i=head[x];i;i=e[i].next)
    {
        if (e[i].to==fa) continue;
        if (!go(e[i].to,x)) return se[x]=0;
    }
    return se[x]=1;
}

bool check(int x)
{
    memset(se,0,sizeof se);
    int nn=0,na=0;
    for (int i=1;i<=m;i++)
    {
        long long dist=0;
        int anc=up(army[i],dist);
        if (f[anc][0]==1&&(dist+dis[anc][0])<mid)
            A[++na].pos=anc,A[na].dis=mid-dist-dis[anc][0];
        else se[anc]=true;
    }
    for (int i=head[1];i;i=e[i].next)
    {
        int v=e[i].to;
        if (!go(v,1)) C[++nn].pos=v,C[nn].dis=e[i].dis;
    }
    if (nn>na) return 0;
    std::sort(A+1,A+na+1,cmp),std::sort(C+1,C+nn+1,cmp);
    int j=1;
    for(int i=1;i<=na;i++)
    {
        if (!se[A[i].pos]) se[A[i].pos]=true;
        else if(C[j].dis<=A[i].dis) se[C[j].pos]=true;
        while (se[C[j].pos]&&j<=nn) j++;
    }
    return j>nn;
}

int main()
{
    scanf("%d",&n);
    for (int i=1;i<n;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        r+=z;
        add(x,y,z),add(y,x,z);
    }
    scanf("%d",&m);
    for (int i=1;i<=m;i++) scanf("%d",&army[i]);
    int notre=0;
    for (int i=head[1];i;i=e[i].next) notre++;
    if (notre>m)
    {
        printf("-1");
        return 0;
    }
    dfs(1,0);
    while (l<=r)
    {
        mid=(l+r)>>1;
        if (check(mid))
        {
            ans=mid;
            r=mid-1;
        }
        else l=mid+1;
    }
    printf("%lld",ans);
}
时间: 2024-11-07 16:16:22

【二分+贪心+倍增】【NOIP2012】疫情控制的相关文章

NOIP2012 疫情控制

Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境 城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境 城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点.但特别要注意的是, 首都是不能建立检查点的. 现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队.一支军队可以

【二分答案+lca】疫情控制

版权声明:本篇随笔版权归作者Etta(http://www.cnblogs.com/Etta/)所有,转载请保留原地址! Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点.但特别要注意的是

习题:疫情控制(二分+倍增+贪心)

noip2012疫情控制 描述H国有n个城市,这n个城市用n-1条双向道路相互连通构成一棵树,1号城市是首都,也是树中的根节点. H国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点.但特别要注意的是,首都是不能建立检查点的. 现在,在H国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队.一支军队可以在有道路连接的城市间移动,

洛谷P1084 [NOIP2012提高组Day2T3]疫情控制

P1084 疫情控制 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从 首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点.但特别要注意的是,首都是不能建立检查点的. 现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队.一支军队可以

luoguP1084 疫情控制(题解)(搜索+贪心)

luoguP1084 疫情控制 题目 #include<iostream> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #define il inline #define rg register #define ll long long #define N 60000 #define inf 21474

codevs1218 疫情控制

疫情控制(blockade.cpp/c/pas)[问题描述]H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点.H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点.但特别要注意的是,首都是不能建立检查点的.现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎

【noip 2012】提高组Day2T3.疫情控制

Description H国有n个城市,这n个城市用n-1条双向道路相互连通构成一棵树,1号城市是首都,也是树中的根节点. H国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点.但特别要注意的是,首都是不能建立检查点的. 现在,在H国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队.一支军队可以在有道路连接的城市间移动,并在除

luoguP1084疫情控制

原题地址 题目分析 我们要明确我们做什么,一步一步慢慢来,否则会被这题逼疯. 1.预处理倍增 我们会发现,离根节点越近的节点,控制的节点更多.所以由贪心的思想,所有的军队都要尽可能地往根节点走. ”往上提“类型问题一般使用倍增优化. 好大的,那么我们可以dfs一遍,将倍增要用的一些值都处理好(见代码) 2.二分答案 军队可以同时移动,说明我们要控制传染病的时间是军队移动到位时,移动时间最长的军队的移动时间.而我们要求最小值,即要求最大化最小值. 二分答案一般用于求最大化最小值,最小化最大值. 所

P1084 疫情控制

题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点.但特别要注意的是,首都是不能建立检查点的. 现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队.一支军队可以在有道路连接的城市间移动