疫情控制 blockad

题目描述

H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是树中的根节点。

H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境 城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境 城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是, 首都是不能建立检查点的。 现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在 一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等 于道路的长度(单位:小时)。

请问最少需要多少个小时才能控制疫情。注意:不同的军队可以同时移动。

输入

第一行一个整数 n,表示城市个数。

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

接下来一行一个整数 m,表示军队个数。

接下来一行 m 个整数,每两个整数之间用一个空格隔开,分别表示这 m 个军队所驻扎 的城市的编号。

输出

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

样例输入

4
1 2 1
1 3 2
3 4 3
2
2 2

样例输出

3

提示

【样例解释】

第一支军队在 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

来源

NOIP2012提高组Day2


solution

容易发现答案具有单调性。

二分答案,然后尝试构造最优方案。

我们应该让所有点尽可能往上跳,如果步数充裕还可以去到别的子树去驻扎。

可以用倍增的方法算出每个点会跳到哪里,如果能跳到根就记下还能走几步。

那么跳不到根的,他的贡献是确定的,所以可以先确定根的那些儿子是已被处理好了。

然后我们把剩余的点按剩余步数排序。记剩余步数为res

如果一个点跳不回自己来的儿子,并且这个儿子还没处理好,那就让他跳回去。

因为让另一个res>它的点去肯定不优。

接下来就对每一个还未被占领的儿子按占领代价(也就是根到它的长度)排序。

贪心匹配即可。

总结:先找性质,二分完构造最优解。细节需想清楚。

 #include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 50004
#define ll long long
using namespace std;
int n,m,head[maxn],tot,f[maxn][],be[maxn];
int match[maxn],top;
ll l[maxn][],len[maxn];
bool flag[maxn];
struct node{
int v,nex,w;
}e[maxn*];
struct no{
int st,ed;
ll res;
}s[maxn];
void lj(int t1,int t2,int t3){
e[++tot].v=t2;e[tot].w=t3;e[tot].nex=head[t1];head[t1]=tot;
}
void dfs(int k,int fa){
f[k][]=fa;
if(fa==)be[k]=k;
else be[k]=be[fa];
for(int i=head[k];i;i=e[i].nex){
if(e[i].v!=fa){
l[e[i].v][]=e[i].w;
dfs(e[i].v,k);
}
}
}
void work(int k){
bool F=,fl=;
for(int i=head[k];i;i=e[i].nex){
if(e[i].v==f[k][])continue;
work(e[i].v);
if(!fl)fl=,F=;
F&=flag[e[i].v];
}
flag[k]|=F;
}
bool Mr(no a,no b){
return a.res<b.res;
}
bool cmp(int a,int b){
return len[a]<len[b];
}
bool pd(ll mid){ for(int i=;i<=n;i++)flag[i]=;
for(int i=;i<=m;i++){
int k=s[i].st;ll la=mid;
for(int x=;x>=;x--){
if(f[k][x]&&l[k][x]<=la){
la-=l[k][x],k=f[k][x];
}
}
s[i].ed=k;s[i].res=la;
if(k>)flag[k]=;
}
work();
sort(s+,s+m+,Mr);
for(int i=;i<=m;i++){
if(s[i].ed!=||flag[be[s[i].st]])continue;
int b=be[s[i].st];
if(s[i].res<len[b])flag[b]=,s[i].ed=b;
}
top=;
for(int i=head[];i;i=e[i].nex){
if(flag[e[i].v])continue;
match[++top]=e[i].v;
}
sort(match+,match+top+,cmp);
int j=;
for(int i=;i<=top;i++){ int L=len[match[i]];
while((s[j].ed!=||s[j].res<L)&&j<=m)j++;
j++;
if(j>m+)return ;
}
return ;
}
int main(){
cin>>n;
for(int i=,t1,t2,t3;i<n;i++){
scanf("%d%d%d",&t1,&t2,&t3);
lj(t1,t2,t3);lj(t2,t1,t3);
}
dfs(,);
for(int i=head[];i;i=e[i].nex)len[e[i].v]=e[i].w;
for(int j=;j<=;j++)
for(int i=;i<=n;i++){
f[i][j]=f[f[i][j-]][j-];
l[i][j]=l[i][j-]+l[f[i][j-]][j-];
}
cin>>m;
for(int i=;i<=m;i++)scanf("%d",&s[i].st);
ll l=,r=1e16;
while(l<r){
ll mid=l+r>>;
if(pd(mid))r=mid;
else l=mid+;
}
if(l==1e16)puts("-1");
else cout<<l<<endl;
return ;
}

疫情控制 blockade的更多相关文章

  1. codevs1218 疫情控制

    疫情控制(blockade.cpp/c/pas)[问题描述]H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点.H 国的首都爆发了一种危害 ...

  2. Codevs 1218 疫情控制 2012年NOIP全国联赛提高组

    1218 疫情控制 2012年NOIP全国联赛提高组 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description H 国有 n 个城市,这 ...

  3. 【NOIP2012】 疫情控制

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

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

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

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

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

  6. 疫情控制 2012年NOIP全国联赛提高组(二分答案+贪心)

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

  7. CH6301 疫情控制

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

  8. luoguP1084 疫情控制(题解)(搜索+贪心)

    luoguP1084 疫情控制 题目 #include<iostream> #include<cstdlib> #include<cstdio> #include& ...

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

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

随机推荐

  1. springBoot支持PageHelp插件使用学习笔记

    首先在springboot项目的maven中加入依赖(版本可能需要自己选择合适的) <dependency> <groupId>com.github.pagehelper< ...

  2. VM12虚拟机安装os x 10.11系统以及注意事项

    一.安装步骤 原文链接:https://blog.csdn.net/soachenshui/article/details/49251513 https://blog.csdn.net/soachen ...

  3. 银行卡验证API

    一.银联开放平台 https://open.unionpay.com/tjweb/api/detail?apiSvcId=21 应用场景 综合数据服务平台是银联为接入商户提供的综合数据认证服务接口,目 ...

  4. linux系统批量创建用户和生成8位随机密码

    1.1    脚本案例 批量创建20个用户,用户名为user1-user20,并生成8位随机登录密码,用户组采用键盘输入的方式,并将用户名及登录密码保存到/tmp/create_user.txt普通文 ...

  5. nodejs的http-server--web前端福利

    很多web前端在日常开发的时候可能会想常开发是谁. 不好意思,说错了. 很多web前端在日常开发的时候总是避免不了让所写页面在服务器环境下执行. 比如当你在用angularjs的route模块等等等. ...

  6. python_字符串_常用处理

    1. 输出原序列的反向互补序列 in1 = open("brca1.fasta", "r") out1 = open("re_brca1.fasta& ...

  7. Python学习之高级特性

    切片 在Python基础篇里,我们知道Python的可序列对象可以通过索引号(下标)来引用对象元素,索引号可以由0开始从左向右依次获取,可以从-1开始由右向左获取.这种方法可以帮助我们依次获取我们想要 ...

  8. Apache安装之后,在浏览器输入ip无法访问

    博主本来在linux下面配置安装了apache,然后用浏览器输入ip却无法访问 就一直在想是不是dns无法解析的问题,最后才发现原来是防火墙的原因, 在linux下面 service iptables ...

  9. Wind Of Change

    Wind of change until the end  变革的风一直吹直至最后 You will see that I will be your friend 你会看见我成为你的朋友 If you ...

  10. STM8S PWM输出停止后 IO口电平输出

    STM8S有许多定时器支持PWM输出,但在停止定时器后,IO口电平到底是多少呢?或高或低. 因此,为了确定PWM停止输出电平后其对应的值是多少,我们在停止PWM输出时需要对CCMR1寄存器进行设置. ...