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 国的首都爆发了一种危害性极高的传染病.当 ...
随机推荐
- Java基础篇(01):基本数据类型,核心点整理
本文源码:GitHub·点这里 || GitEE·点这里 一.基本类型 1.基本类型 不使用New创建,声明一个非引用传递的变量,且变量的值直接置于堆栈中,大小不随运行环境变化,效率更高.使用new创 ...
- Yuchuan_Linux_C编程之一 Vim编辑器的使用
一.整体大纲 二.Vim 编辑器的使用 vi -- vim vim是从vi发展过来的一款文本编辑器 vi a.txt 前提: 安装了vim软件 工作模式: 1. 命令模式 -- 打开 ...
- 网络编程概念 和OSI七层结构简介
什么是网络编程 网络通常指的是计算机中的互联网,是由多台计算机通过网线或其他媒介相互链接组成的 编写基于网络的应用程序的过程序称之为网络编程 学习网络编程就是要学习利用网络来与另一台计算机相互传输数据 ...
- sonarqube配置全指南,集成阿里巴巴p3c规范
环境准备 内置数据库 Sonar安装成功后,默认内置H2数据库,用于记录单次的扫描结果,对同一个project重复扫码,会覆盖之前的扫描记录,所以H2 数据库只应用于测试,不可以用于生产环境,那如果你 ...
- MySQL敏感数据加密及解密
大数据时代的到来,数据成为企业最重要的资产之一,数据加密的也是保护数据资产的重要手段.本文主要在结合学习通过MySQL函数及Python加密方法来演示数据加密的一些简单方式. 1. 准备工作 为了便于 ...
- golang 交叉编译 win开发 linux生产
windows平台之下使用 go env 能看到go本身的配置的环境变量,其中红框框起来的变量是交叉编译需要改动的选项, 由于是win平台开发,但是跑起来的程序都是在linux,所以linux转win ...
- Redis主从原理及哨兵模式
1.Redis主从搭建 主从的搭建很简单,主节点设置连接密码,从节点的配置上主节点的ip和端口,以及密码,一般从节点我们都设置只读模式. 主节点配置: 主节点密码: requirepass xxx 从 ...
- HashMap底层源码剖析
HashMap底层源码剖析 一.HashMap底层用到的数据结构 数组+单向链表+红黑树 数组:数组每一项都是一个链表,其实就是数组和链表的结合体 单向链表:当法神hash碰撞时,首先会找到数组对应位 ...
- JS高精度乘法计算问题(牛客网乘法-求 a 和 b 相乘的值,a 和 b 可能是小数,需要注意结果的精度问题)
用到的知识点===> toFixed(num); toFixed() 方法可把 Number 四舍五入为指定小数位数的数字; 参数num: 代表小数位数: 例:var num = 5.56789 ...
- 返回运行方法,可以写在一行 callback&&callback()
return DiscountMap[discountType] && DiscountMap[discountType](price)