题目描述

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. Golang 编写 Tcp 服务器

    Golang 作为广泛用于服务端和云计算领域的编程语言,tcp socket 是其中至关重要的功能.无论是 WEB 服务器还是各类中间件都离不开 tcp socket 的支持. Echo 服务器 拆包 ...

  2. linux中的vi命令

    linux的重要的几个命令如下: ①,光标的操作 1,gg,G,nG,:n gg移到文档的开头一行,G移动到最后一行,nG移动到第n行,到指定的行. 2,H,M,L 光标分别移动到这个界面的最上边,中 ...

  3. 活动预告丨易盾CTO朱浩齐将出席2018 AIIA大会,分享《人工智能在内容安全的应用实践》

    本文来自网易云社区 对于很多人来讲,仿佛昨天才燃起来的人工智能之火,转眼间烧遍了各个角落,如今我们的生活中,处处渗透着人工智能.10月16日,2018年 AIIA人工智能开发者大会在苏州举办,网易云易 ...

  4. 遇到的Ajax相关问题

  5. Python+fiddler(基于Cookie绕过验证码自动登录)

    案例:使用Cookie绕过百度验证码自动登录账户 步骤: 1.浏览器进入百度首页,点击登录按钮,输入相关信息(注意:暂时不要点击登录按钮) 2.进入fiddler,首先获取证书,Tools--> ...

  6. xtu summer individual 1 E - Palindromic Numbers

    E - Palindromic Numbers Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %l ...

  7. Monkey King(左偏树)

    洛谷传送门 每次给出要争吵的猴子a和b,用并查集判断如果他们是朋友输出-1 如果不是,找出a,b在的堆的根A,B,分别合并A,B的左右孩子,再合并一下. 之后把A,B的数据更改一下:权值除以2,左右孩 ...

  8. 洛谷P1432 倒水问题

    题目背景 In the movie "Die Hard 3", Bruce Willis and Samuel L. Jackson were confronted with th ...

  9. docker改变镜像源

    sudo echo “DOCKER_OPTS=\”\$DOCKER_OPTS –registry-mirror=http://your-id.m.daocloud.io -d\”” >> ...

  10. Enchantress(hdu 3922)

    首先考虑覆盖三个点的情况,有两种情况: ①:三个点都在圆上,则该圆是三角形的外接圆 ②:两个点在圆上,第三个点在圆内,且在圆上的两个点之间的线段一定是直径 如果是多个圆,就不停地迭代. 有一点重要的是 ...