疫情控制 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 ;
}

最新文章

  1. jQuery.grep()
  2. 初学HTML 表单交互标签
  3. 头一次试验angularjs
  4. u-boot平台的建立,驱动的添加,索引的创建,命令机制的实现.
  5. Java多线程开发技巧
  6. AngularJS快速入门指南20:快速参考
  7. 加密解密及其javascript实现
  8. iOS-多线程之NSOperation
  9. Base64加密解密原理以及代码实现(VC++)
  10. vs调试 本地IIS
  11. c语言结构体中的冒号的用法
  12. Mvc网站开发知识
  13. MongoDB(两)mongoDB基本介绍
  14. 使用myeclipse将Javaj项目标ar套餐邂逅classnotfound解决问题的方法
  15. Microsoft Push Notification Service(MPNS)的最佳体验
  16. MyBatis 传入参数之parameterType
  17. maven项目-修复Plugin execution not covered by lifecycle configuration: org.codehaus.mojo:build-helper-maven-plugin:1.8:add-resource (execution: add-resource, phase: generate-resources) pom.xml报错
  18. 【简单易用的傻瓜式图标设计工具】Logoist 3.1 for Mac
  19. PHP中new static()与new self()的区别异同分析
  20. PHP之缓存雪崩,及解决方法(转)

热门文章

  1. 【赛时总结】◇赛时&#183;V◇ Codeforces Round #486 Div3
  2. CSS之美化页面
  3. datatable 单元格默认文本
  4. Qt的QWebChannel和JS、HTML通信/交互驱动百度地图
  5. iOS-delegate设计模式
  6. Android MultiType第三方库的基本使用和案例+DiffUtil的简单用法
  7. 网络编程介绍(uninx/windows)
  8. 《Cracking the Coding Interview》——第3章:栈和队列——题目6
  9. 《Cracking the Coding Interview》——第2章:链表——题目3
  10. iOS笔记055 - UI总结01