[NOIP2012] day2 T3疫情控制
题目描述
H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点。
H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是,首都是不能建立检查点的。
现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等于道路的长度(单位:小时)。
请问最少需要多少个小时才能控制疫情。注意:不同的军队可以同时移动。
输入输出格式
输入格式:
第一行一个整数 n,表示城市个数。
接下来的 n-1 行,每行 3 个整数,u、v、w,每两个整数之间用一个空格隔开,表示从城市 u 到城市 v 有一条长为 w 的道路。数据保证输入的是一棵树,且根节点编号为 1。
接下来一行一个整数 m,表示军队个数。
接下来一行 m 个整数,每两个整数之间用一个空格隔开,分别表示这 m 个军队所驻扎的城市的编号。
输出格式:
共一行,包含一个整数,表示控制疫情所需要的最少时间。如果无法控制疫情则输出-1。
输入输出样例
说明
【输入输出样例说明】
第一支军队在 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疫情控制的更多相关文章
- 2012Noip提高组Day2 T3 疫情控制
题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到 ...
- NOIP2012 D2 T3 疫情控制 洛谷P1084
题目链接:https://www.luogu.org/problemnew/show/P1084 算法:倍增,二分答案,贪心 + 瞎搞.. 背景:上学长的数论课啥也听不懂,于是前去提高组找安慰.不巧碰 ...
- A 【NOIP2012 day2】疫情控制
时间限制 : 20000 MS 空间限制 : 128000 KB 评测说明 : 2s,128m 问题描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是 ...
- [NOIP2012提高组]疫情控制
题目:洛谷P1084.codevs1218.Vijos P1783. 题目大意:有一棵n个节点的,根为1的带权树和m支军队.每支军队可以在一个点上停下,那么从1开始就不能经过这个点了.现在有m支军队已 ...
- P1084 [NOIP2012 提高组] 疫情控制 (二分答案、贪心)
因为若一个时间限制满足题意,则所有比它大的时间限制一定都满足题意,因此本题答案具有单调性,可以想到二分答案求解. 本题思路不是很难,但细节和代码实现比较复杂. 见牛人博客:https://www.lu ...
- 【NOIP2012】 疫情控制
[NOIP2012] 疫情控制 标签: 倍增 贪心 二分答案 NOIP Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是 ...
- Luogu 1084 NOIP2012 疫情控制 (二分,贪心,倍增)
Luogu 1084 NOIP2012 疫情控制 (二分,贪心,倍增) Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是 ...
- [NOIP2012]疫情控制 贪心 二分
题面:[NOIP2012]疫情控制 题解: 大体思路很好想,但是有个细节很难想QAQ 首先要求最大时间最小,这种一般都是二分,于是我们二分一个时间,得到一个log. 然后发现一个军队,越往上走肯定可以 ...
- NOIP2012 疫情控制 题解(LuoguP1084)
NOIP2012 疫情控制 题解(LuoguP1084) 不难发现,如果一个点向上移动一定能控制更多的点,所以可以二分时间,判断是否可行. 但根节点不能不能控制,存在以当前时间可以走到根节点的点,可使 ...
随机推荐
- 基于 NodeJs 打造 Web 在线聊天室
Socket.IO 简介与基础环境搭建 任务时间:10min ~ 20min 关于 Socket.IO Socket.IO 可以实现在浏览器和服务器之间实时双向通信,本节课程将详细介绍 Socket. ...
- XV内存变化
- 64.JPA命名策略【从零开始学Spring Boot】
[从零开始学习Spirng Boot-常见异常汇总] 在(39.2). Spring Boot Shiro权限管理[从零开始学Spring Boot] 这一章节中有人碰到这样一个问题"导入的 ...
- NOIP2009T3最优贸易(Dfs + spfa)
洛谷传送门 看到这个题,原本想先从后往前dfs,求出能到终点的点,再在这些点里从前往后spfa,用一条边上的两个城市的商品价格的差来作边权,实施过后,发现图中既有负边权,又有回路,以及各种奇奇怪怪的东 ...
- BZOJ1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害
n<=3000个点m<=20000条无向边的图,有p<=n个出发点,每个出发点都不可拆,现拆一些点使每个出发点都不能到达点1,求最小点数. 简单的最小割.每个点拆成两个x和y,无向边 ...
- C++函数的重载,覆盖和隐藏(——高质量编程第14章)
函数重载概念 只有C++才有重载的概念,C语言没有. 靠行参列表的不同来区别不同的重载函数, 若是全局函数和成员函数同名时,不算重载,因为它们的作用域不同,所以成员函数会将全局函数给隐藏(遮蔽)了 ...
- FastDFS+nginx+php的完整应用[转储]
FastDFS功能简介: FastDFS是一个开源的轻量级分布式文件系统,它对文件进行管理,功能包括:文件存储.文件同步.文件访问(文件上传.文件下载)等,解决了大容量存储和负载均衡的问题.特别适合以 ...
- iOS 如何查看崩溃日志
参考网址: [转载]https://www.jianshu.com/p/4de55d73c82b [转载]https://blog.csdn.net/qq_26544491/article/detai ...
- oracle alert 日志位置
Oracle 11g Alert log 文件位置的问题 https://blog.csdn.net/yujin2010good/article/details/7690191 https://blo ...
- DELL IDRAC API接口开发文档翻译及client模块
今天和DELL官网要了一份关于服务器IDRAC 版本7/8 的API开发文档,花了一天的时间,进行了翻译,不一定全部准确,但对于英语不好的人会有所帮助.也不用重复造轮子了.下载链接: IDRAC AP ...