A 【NOIP2012 day2】疫情控制
|
问题描述
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
10
2 1 3
2 3 4
1 4 7
5 1 9
6 1 2
4 7 9
7 8 8
9 8 8
1 10 2
5
2 8 5 4 2
样例输出 2
9
样例输入 3
10
1 2 15606
3 1 2777
4 3 2008
1 5 29898
1 6 31457
7 5 4630
6 8 32496
3 9 27660
10 9 29090
4
9 5 10 3
样例输出 3
56750
提示
【输入输出样例说明】
第一支军队在 2 号点设立检查点,第二支军队从 2 号点移动到 3 号点设立检查点,所需时间为 3 个小时。
【数据范围】
保证军队不会驻扎在首都。
对于 20%的数据,2≤ n≤ 10;
对于 40%的数据,2 ≤n≤50,0<w <105;
对于 60%的数据,2 ≤ n≤1000,0<w <106;
对于 80%的数据,2 ≤ n≤10,000;
对于 100%的数据,2≤m≤n≤50,000,0<w <109。
#include<cstdio>
#include<algorithm>
#include<cctype>
#define ll long long
#define R register int
#define For(i, s, n) for (R i = s; i <= n; ++ i)
#define Getch() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1 ++)
#define maxn 50003
#define Log 17
using namespace std;
int n, u, v, w, m, tot, na, nb;
int End[maxn << ], Len[maxn << ], Next[maxn << ], Last[maxn], Army[maxn], F[maxn][Log + ], vis[maxn], used[maxn], restbj[maxn];
ll ans, l, r, Mid, Dis[maxn][Log + ], restmin[maxn];
char buf[ << ], *p1 = buf, *p2 = buf, obuf[ << ], *O = obuf;
struct node{
int id;
ll rest;
}a[maxn], b[maxn];
inline int read() {
int x = , f = ;
char ch = Getch();
while(!isdigit(ch)){if (ch == '-')f = -; ch = Getch();}
while(isdigit(ch))x = x * + (ch ^ ), ch = Getch();
return x * f;
}
void write(long long x) {
if (x > ) write(x / );
*O ++ = x % + '';
}
void Add(int x, int y, int z) {
End[++ tot] = y;
Len[tot] = z;
Next[tot] = Last[x];
Last[x] = tot;
}
void DFS(int x, int Las_, ll Gone) {
F[x][] = Las_;
Dis[x][] = Gone;
For (i, , Log) {
F[x][i] = F[F[x][i - ]][i - ];
Dis[x][i] = Dis[x][i - ] + Dis[F[x][i - ]][i - ];
}
for (R i = Last[x]; i != ; i = Next[i])
if (End[i] != Las_)DFS(End[i], x, Len[i]);
}
void ini() {
n = read();
scanf("%d", &n);
For (i, , n - ) {
u = read();
v = read();
w = read();
Add(u, v, w);
Add(v, u, w);
r += w;
}
DFS(, , );
m = read();
scanf("%d", &m);
For (i, , m)Army[i] = read();
}
bool cmp(node x,node y) {
return x.rest > y.rest;
}
int checkok(int x, int las){ //dfs找未被“封死”的子树
R bj = , i, bbj = ;
if (vis[x])return ;
for (i = Last[x]; i != ; i = Next[i]) {
if (End[i] == las)continue;
bbj = ;
if (!checkok(End[i], x)) {
bj = ;
if (x == )b[++ nb].id = End[i], b[nb].rest = Len[i];
else return ;
}
}
if(!bbj)return ;
return bj;
}
bool Check(ll Lim) {
R i, j, x, now;
ll num;
na = nb = ;
For (i, , n)vis[i] = restbj[i] = ;
For (i, , m)used[i] = ;
For (i, , m) {
x = Army[i], num = ;
for (j = ; j >= ; -- j) //上提军队
if (F[x][j] > && num + Dis[x][j] <= Lim)
num += Dis[x][j], x = F[x][j];
if (F[x][] == && num + Dis[x][] <= Lim){ //处理剩余路程
a[++ na].rest = Lim - num - Dis[x][], a[na].id = i;
if (!restbj[x] || a[na].rest < restmin[x])
restmin[x] = a[na].rest, restbj[x] = i;
} else vis[x] = ;
}
if (checkok(, ))return ;
sort(a + , a + + na, cmp), sort(b + , b + + nb, cmp); //军队在子树间转移
now = ;
used[] = ;
For (i, , nb) {
if (!used[restbj[b[i].id]]) {
used[restbj[b[i].id]] = ;
continue;
}
while (now <= na && (used[a[now].id] || a[now].rest < b[i].rest))++ now;
if (now > na)return ;
used[a[now].id] = ;
}
return ;
}
void solve() {
while (l <= r) {
Mid = (l + r) >> ;
if (Check(Mid)) {
ans = Mid;
r = Mid - ;
} else l = Mid + ;
}
write(ans);
}
int main() {
ini();
solve();
fwrite(obuf, O - obuf, , stdout);
return ;
}
A 【NOIP2012 day2】疫情控制的更多相关文章
- 【NOIP2012】 疫情控制
[NOIP2012] 疫情控制 标签: 倍增 贪心 二分答案 NOIP Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是 ...
- [LOJ2607]【NOIP2012】疫情控制
题意: 题目描述 H 国有n个城市,这n个城市用n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边 ...
- 【noip2012】疫情控制
题意: 给出一颗n个节点有边权的树 和m个军队所在的位置 军队从某节点移动到相邻节点要花费边长度的时间 求最少要多少时间使得根节点(编号为1)到每个叶子的路径上最少有一支军队(根节点不能有军队) 题解 ...
- 【NOIP2012】疫情控制(二分,倍增,贪心)
洛谷上的题目链接,题目不在赘述 题解 既然要时间最短,首先考虑二分. 因此,考虑二分时间,问题转换为如何检查能否到达. 如果一支军队一直向上走,能够到达根节点,那么他可以通过根节点到达其他的节点,因此 ...
- NOIP2012 D2T3 疫情控制 题解
题面 这道题由于问最大值最小,所以很容易想到二分,但怎么验证并且如何实现是这道题的难点: 首先我们考虑,对于一个军队,尽可能的往根节点走(但一定不到)是最优的: 判断一个军队最远走到哪可以树上倍增来实 ...
- Luogu 1084 NOIP2012 疫情控制 (二分,贪心,倍增)
Luogu 1084 NOIP2012 疫情控制 (二分,贪心,倍增) Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是 ...
- [NOIP2012]疫情控制 贪心 二分
题面:[NOIP2012]疫情控制 题解: 大体思路很好想,但是有个细节很难想QAQ 首先要求最大时间最小,这种一般都是二分,于是我们二分一个时间,得到一个log. 然后发现一个军队,越往上走肯定可以 ...
- NOIP2012 疫情控制 题解(LuoguP1084)
NOIP2012 疫情控制 题解(LuoguP1084) 不难发现,如果一个点向上移动一定能控制更多的点,所以可以二分时间,判断是否可行. 但根节点不能不能控制,存在以当前时间可以走到根节点的点,可使 ...
- 洛谷P1084 [NOIP2012提高组Day2T3]疫情控制
P1084 疫情控制 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控 ...
- 疫情控制 blockade
疫情控制 blockad 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当 ...
随机推荐
- idea使用Tomcat部署war 和 war exploded的区别
war模式:将WEB工程一包的形式上传到服务器中.war exploded模式:将WEB工程以当前文件夹的位置关系上传到服务器.解析:war 模式这种可以称为是发布模式(完整的项目),将项目打成war ...
- Unity 相机平移、旋转、缩放
内容不多,一个脚本,直接上代码 using System.Collections; using System.Collections.Generic; using UnityEngine; publi ...
- C#制作密码文本框
2020-03-14 每日一例第7天 1.新建窗体windowform,修改text值: 2.两个按钮后台代码: private void button1_Click(object sender, E ...
- css 固比固模型
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Python——项目-小游戏2-动画绘制
实现游戏循环还有事件的监听 在上一讲中 你需要完成这样的这样的效果, 如果你还没有完成,请不要继续往下阅读!!切记切记切记.,重要的事情说三遍 我们来看一下什么是游戏循环 所谓的游戏循环很好的理解 就 ...
- div或者p标签单行和多行超出显示省略号
单行文本溢出显示省略号 overflow: hidden;text-overflow:ellipsis;white-space: nowrap;多行文本显示省略号 display: -webkit-b ...
- [剑指offer]62.圆圈中最后剩下的数字
62.圆圈中最后剩下的数字 题目 0,1,...,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字.求出这个圆圈里剩下的最后一个数字. 例如,0.1.2.3.4这5个数字组成 ...
- 升级 nop 4.1 Incorrect syntax near 'OFFSET'. Invalid usage of the option NEXT in the FETCH statement.
Incorrect syntax near 'OFFSET'. Invalid usage of the option NEXT in the FETCH statement. nop.web 项目 ...
- 滑动窗口-Moving Stones Until Consecutive II
2020-02-20 16:34:16 问题描述: 问题求解: public int[] numMovesStonesII(int[] stones) { int n = stones.length; ...
- PAT-B 1005. 继续(3n+1)猜想 (25) c++
1005. 继续(3n+1)猜想 (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 卡拉兹(Callatz ...