题目描述

H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点。

H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是,首都是不能建立检查点的。

现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等于道路的长度(单位:小时)。

请问最少需要多少个小时才能控制疫情。注意:不同的军队可以同时移动。

输入输出格式

输入格式:

第一行一个整数 n,表示城市个数。

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

接下来一行一个整数 m,表示军队个数。

接下来一行 m 个整数,每两个整数之间用一个空格隔开,分别表示这 m 个军队所驻扎的城市的编号。

输出格式:

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

输入输出样例

输入样例#1:
复制

4
1 2 1
1 3 2
3 4 3
2
2 2
输出样例#1: 复制

3

说明

【输入输出样例说明】

第一支军队在 2 号点设立检查点,第二支军队从 2 号点移动到 3 号点设立检查点,所需时间为 3 个小时。

【数据范围】

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

对于 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。

NOIP 2012 提高组 第二天 第三题

分析

首先本题明确我们要做什么。

1.我们会发现,离根节点越近的节点,控制的节点更多。所以由贪心的思想,所有的军队都要尽可能地往根节点走。

  预处理倍增

2.我们是要求走的最远的军队所走的距离,最小化最大值。

  二分答案

3.让军队倍增的往上跳,处理哪些点可以到根节点并且还有剩余时间。

4.寻找哪些未被控制的子树,注意:如果该节点的所有儿子都被控制了,那么就相当于该节点也被控制了。

5.将我们已经记录好了的可以到根节点的军队按照剩余时间从大到小排序。

 将未被控制的子树按照到子树到根节点的距离从大到小排序。

 然后依次处理未被控制的子树要由哪支军队来管辖。

    贪心(最难得部分也是最重要的部分)

错误贪心:我先讲我一开始错误的贪心,先从大到小排序,如果一个子树上有一个军队从那里跳上来,我就先让他受自己的子树。但我后来发现,假如当前这个军队的剩余时间还有很多,他就可以去控制其他的节点,而让其他的军队来守护他的子树。正确贪心:也是先从大到小排序,如果当前军队到另一个子树上,而当前这个子树上有军队,我就先用这个子树上剩余时间最短的来控制它,再用继续循环,直到找到一个子树没有军队驻扎在那里的,就去控制它。显然这样的贪心肯定是对的。

本题差不多就是这样了。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
ll kzj,pwq;
ll last[],len,army[],dep[][],fa[][],n,m,sum[];
bool vis[];
ll viss[],re[],shu[];
struct node
{
ll to,next,w;
}a[];
struct NODE
{
ll rest,id,visss,num;
}q[],p[];
bool cmp(NODE a,NODE b)
{
return a.rest>b.rest;
}
void add(ll a1,ll a2,ll a3)
{
len++;
a[len].to=a2;
a[len].w=a3;
a[len].next=last[a1];
last[a1]=len;
}
void dfs(ll x,ll father)
{
ll k=;
for(ll i=last[x];i;i=a[i].next)
{
ll to=a[i].to;
if(to==father)
continue;
k++;sum[x]=k;
fa[to][]=x;
dep[to][]=a[i].w;
dfs(to,x);
}
}
void zuxian()
{
for(ll j=;j<=;j++)
for(ll i=;i<=n;i++)
{
fa[i][j]=fa[fa[i][j-]][j-];
dep[i][j]=dep[i][j-]+dep[fa[i][j-]][j-];
}
}
void ok(ll x,ll father)
{
ll k=;
for(ll i=last[x];i;i=a[i].next)
{
ll to=a[i].to;
if(to==father) continue;
ok(to,x);
if(vis[to])
k++;
if(k==sum[x])
vis[x]=;
}
}
bool check(ll mid)
{
memset(shu,,sizeof(shu));
memset(p,,sizeof(p));
memset(q,,sizeof(q));
memset(viss,,sizeof(viss));
memset(re,,sizeof(re));
memset(vis,,sizeof(vis));
pwq=,kzj=;
for(ll i=;i<=m;i++)
{
ll t=army[i],num=;
for(ll j=;j>=;j--)
{
if(fa[t][j]>&&num+dep[t][j]<=mid)
num+=dep[t][j],t=fa[t][j];
}
if(fa[t][]==&&num+dep[t][]<mid)
{
q[++pwq].rest=mid-num-dep[t][];
q[pwq].id=t;
q[pwq].num=num;
}
else vis[t]=;
}
ok(,);
if(vis[]==) {return ;}
else
{
for(ll i=last[];i;i=a[i].next)
{
ll to=a[i].to;
if(!vis[to])
{
p[++kzj].rest=a[i].w;
p[kzj].id=to;
}
}
sort(p+,p++kzj,cmp);
sort(q+,q++pwq,cmp);
for(int i=;i<=pwq;i++)
{
int t=q[i].id;
int num=q[i].num;
if(!viss[t])
viss[t]=,re[t]=mid-num-dep[t][],shu[t]=i;
else if(re[t]>mid-num-dep[t][])
{
re[t]=mid-num-dep[t][];
shu[t]=i;
}
}
if(kzj>pwq) return ;
ll ppp=;
for(ll i=;i<=kzj;i++)
{
if(shu[p[i].id]&&!q[shu[p[i].id]].visss)
{
q[shu[p[i].id]].visss=;
continue;
}
while(q[ppp].visss==)
ppp++;
if(ppp>pwq) return ;
if(q[ppp].rest<p[i].rest)
return ;
q[ppp].visss=;
}
}
return ;
}
int main()
{
cin>>n;ll ans=-,x,y,z;
for(ll i=;i<n;i++)
{
scanf("%lld%lld%lld",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
cin>>m;
for(ll i=;i<=m;i++)
scanf("%lld",&army[i]);
dfs(,);zuxian();
ll l=,r=;
while(l<=r)
{
ll mid=(l+r)/;
if(check(mid))
r=mid-,ans=mid;
else
l=mid+;
}
cout<<ans;
}

[NOIP2012] day2 T3疫情控制的更多相关文章

  1. 2012Noip提高组Day2 T3 疫情控制

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

  2. NOIP2012 D2 T3 疫情控制 洛谷P1084

    题目链接:https://www.luogu.org/problemnew/show/P1084 算法:倍增,二分答案,贪心 + 瞎搞.. 背景:上学长的数论课啥也听不懂,于是前去提高组找安慰.不巧碰 ...

  3. A 【NOIP2012 day2】疫情控制

    时间限制 : 20000 MS   空间限制 : 128000 KB 评测说明 : 2s,128m 问题描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是 ...

  4. [NOIP2012提高组]疫情控制

    题目:洛谷P1084.codevs1218.Vijos P1783. 题目大意:有一棵n个节点的,根为1的带权树和m支军队.每支军队可以在一个点上停下,那么从1开始就不能经过这个点了.现在有m支军队已 ...

  5. P1084 [NOIP2012 提高组] 疫情控制 (二分答案、贪心)

    因为若一个时间限制满足题意,则所有比它大的时间限制一定都满足题意,因此本题答案具有单调性,可以想到二分答案求解. 本题思路不是很难,但细节和代码实现比较复杂. 见牛人博客:https://www.lu ...

  6. 【NOIP2012】 疫情控制

    [NOIP2012] 疫情控制 标签: 倍增 贪心 二分答案 NOIP Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是 ...

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

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

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

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

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

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

随机推荐

  1. Crossed Ladders 求街道宽度 (二分法)

    Description A narrow street is lined with tall buildings. An x foot long ladder is rested at the bas ...

  2. hihocoder 1584 Bounce (数学 && 规律) ACM-ICPC北京赛区2017网络赛

    题意: 给定一副n*m的格子图, 问从左上角的点开始往右下角滑,碰到墙壁就反弹, 碰到角落就停止, 问恰好经过一次的格子有多少个. 如图,恰好经过一次的格子有39个. 分析: 首先要引入两个概念, “ ...

  3. redis异常信息:MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk.。。。。

    redis.exceptions.ResponseError: MISCONF Redis is configured to save RDB snapshots, but it is current ...

  4. Leetcode 319.灯泡开关

    灯泡开关 初始时有 n 个灯泡关闭.第 1 轮,你打开所有的灯泡.第 2 轮,每两个灯泡你关闭一次.第 3 轮,每三个灯泡切换一次开关(如果关闭则开启,如果开启则关闭).第 i 轮,每 i 个灯泡切换 ...

  5. UITableView点击背景

    系统自定义的点击背景有时间觉得效果不好想换个 - (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelect ...

  6. BZOJ4551 - [TJOI2016]树

    Portal Description 给出一棵\(n(n\leq10^5)\)个点的以\(1\)为根的有根树,进行\(Q(Q\leq10^5)\)次操作: 标记一个点\(x\). 询问\(x\)的祖先 ...

  7. X230 安装 EI Capitan 10.11.5 总结

    /*     写这个文章的目的主要是为了帮助我自己理清思路,如果能顺便帮助到您.even better   */ 在动手之前大致浏览了 远景论坛(国内第一黑苹果社区)置顶帖的全部内容 [新人请看]远景 ...

  8. html5的新通讯技术socket.io,实现一个聊天室

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. Circling Round Treasures(codeforces 375c)

    题意:要求在一张网格图上走出一条闭合路径,不得将炸弹包围进去,使围出的总价值减去路径长度最大. /* 类似于poj3182的做法,只不过出现了多个点,那么就用状态压缩的方法记录一个集合即可. */ # ...

  10. SA模板

    #include<cstdio> #include<algorithm> #include<cstring> using namespace std; ; char ...