时间限制 : 20000 MS   空间限制 : 128000 KB
评测说明 : 2s,128m
问题描述

H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点。
H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是,首都是不能建立检查点的。现在,在 H国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。

一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等于道路的长度(单位:小时)。请问最少需要多少个小时才能控制疫情。注意:不同的军队可以同时移动。

输入格式

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

输出格式

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

样例输入 1


1 2 1 
1 3 2 
3 4 3 

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】疫情控制的更多相关文章

  1. 【NOIP2012】 疫情控制

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

  2. [LOJ2607]【NOIP2012】疫情控制

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

  3. 【noip2012】疫情控制

    题意: 给出一颗n个节点有边权的树 和m个军队所在的位置 军队从某节点移动到相邻节点要花费边长度的时间 求最少要多少时间使得根节点(编号为1)到每个叶子的路径上最少有一支军队(根节点不能有军队) 题解 ...

  4. 【NOIP2012】疫情控制(二分,倍增,贪心)

    洛谷上的题目链接,题目不在赘述 题解 既然要时间最短,首先考虑二分. 因此,考虑二分时间,问题转换为如何检查能否到达. 如果一支军队一直向上走,能够到达根节点,那么他可以通过根节点到达其他的节点,因此 ...

  5. NOIP2012 D2T3 疫情控制 题解

    题面 这道题由于问最大值最小,所以很容易想到二分,但怎么验证并且如何实现是这道题的难点: 首先我们考虑,对于一个军队,尽可能的往根节点走(但一定不到)是最优的: 判断一个军队最远走到哪可以树上倍增来实 ...

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

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

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

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

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

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

  9. 洛谷P1084 [NOIP2012提高组Day2T3]疫情控制

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

  10. 疫情控制 blockade

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

随机推荐

  1. python3 flask shell

    python shell来操作flask flask shell 报错: from flask_bootstrap import BootstrapImportError: No module nam ...

  2. 关于PHP命名空间的讨论

    什么是命名空间? 根据php.net官方翻译文档描述,命名空间是这样定义的: 什么是命名空间?从广义上来说,命名空间是一种封装事物的方法. 在PHP中,命名空间用来解决在编写类库或应用程序时创建可重用 ...

  3. 以正确的方式下载和配置 ASP.NET Core 官方源码

    我们可以在Github上面直接查看ASP.NET Core 3.x的源代码,但是我们也可以把源代码下载下来进行查看. 而下载源代码进行查看有很多好处: 任意的导航源代码 内置了一个示例项目 直接调试源 ...

  4. CSS 文本截断方案

    单行截断 .ellipsis { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } 此方法兼容到ie6过.不过只能单行 ...

  5. celery异步任务 定时任务

    以前项目中用到过 celery ,但是没怎么记笔记,现在在记一下,方便以后用.   Celery.png 问:Celery 是什么? 答:Celery 是一个由 Python 编写的简单.灵活.可靠的 ...

  6. C++ 按行读取文件并打印

    #include<iostream> #include<fstream> #include<string> #include <vector> #inc ...

  7. 测试必知必会系列- Linux常用命令 - history

    21篇测试必备的Linux常用命令,每天敲一篇,每次敲三遍,每月一循环,全都可记住!! https://www.cnblogs.com/poloyy/category/1672457.html 查看历 ...

  8. 我的Keras使用总结(1)——Keras概述与常见问题整理

    今天整理了自己所写的关于Keras的博客,有没发布的,有发布的,但是整体来说是有点乱的.上周有空,认真看了一周Keras的中文文档,稍有心得,整理于此.这里附上Keras官网地址: Keras英文文档 ...

  9. 【spring springmvc】springmvc使用注解声明控制器与请求映射

    目录 概述 壹:注解说明 贰:实现注解声明控制器与请求映射 一:使用controller 二:配置包扫描与视图解析器 1.配置包扫描 2.配置试图解析器 三:配置部署描述符 1.读取spring-mv ...

  10. JavaScript每日学习日记(2)

    8.13.2019 1. 正则表达式常见字符串方法: search( ) , replace( ) var str = "Visit Website"; var n = str.s ...