题目描述 Description

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

也是树中的根节点。

H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境

城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境

城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是,

首都是不能建立检查点的。

现在,在 H国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军

队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在

一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等

于道路的长度(单位:小时)。

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

输入描述 Input Description

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

接下来的 n-1 行,每行 3 个整数,u、v、w,每两个整数之间用一个空格隔开,表示从

城市 u 到城市 v 有一条长为 w 的道路。数据保证输入的是一棵树,且根节点编号为 1。

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

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

的城市的编号。

输出描述 Output Description

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

样例输入 Sample Input

4

1 2 1

1 3 2

3 4 3

2

2 2

样例输出 Sample Output

3

数据范围及提示 Data Size & Hint

【输入输出样例说明】

第一支军队在 2 号点设立检查点,第二支军队从 2 号点移动到 3 号点设立检查点,所需

时间为 3 个小时。

【数据范围】

保证军队不会驻扎在首都。

对于 20%的数据,2≤ n≤ 10;

对于 40%的数据,2 ≤n≤50,0<w <10^5;

对于 60%的数据,2 ≤ n≤1000,0<w <10^6;

对于 80%的数据,2 ≤ n≤10,000;

对于 100%的数据,2≤m≤n≤50,000,0<w <10^9。

/*
二分+倍增+贪心
①题目要求使最长时间最短,那我们会想到二分答案,二分出答案之后,
要使各处的军队尽量向上跑才最优,因为这样能覆盖尽量多的点。
②对于能跑到根节点的点,我们就记录他跑到根节点后最多还能跑多远,
并且记录下他是从根节点的哪那个子节点来的,这些信息都记录到b结构体中。
③对于那些跑不到根节点的军队,我们让他待在能跑到的最高处,而且进行一遍深搜,
如果某个点的所有子节点都保证能覆盖,我们就认为它也能被覆盖。
④在根节点的子节点中找到没有被覆盖的,然后用b结构体中的军队来分配给他们,
分配原则是:如果b结构体军队原来的点没有覆盖,就覆盖原来的,否则,从小到大一一对应。
*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define M 50010
using namespace std;
int head[M],pos[M],fa[M][],dis[M][],vis[M],n,m;
struct node{int v,pre,t;};node e[M*];
struct Node{int u,v;};Node b[M],c[M];
int read()
{
char c=getchar();int num=,flag=;
while(c<''||c>''){if(c=='-')flag=-;c=getchar();}
while(c>=''&&c<=''){num=num*+c-'';c=getchar();}
return num*flag;
}
void add(int i,int x,int y,int z)
{
e[i].v=y;
e[i].t=z;
e[i].pre=head[x];
head[x]=i;
}
bool cmp(const Node&x,const Node&y)
{
return x.v<y.v;
}
void dfs(int now,int from)
{
fa[now][]=from;
for(int i=head[now];i;i=e[i].pre)
if(e[i].v!=from)
{
dis[e[i].v][]=e[i].t;
dfs(e[i].v,now);
}
}
void get_fa()
{
for(int j=;j<=;j++)
for(int i=;i<=n;i++)
{
fa[i][j]=fa[fa[i][j-]][j-];
dis[i][j]=dis[i][j-]+dis[fa[i][j-]][j-];
}
}
void color(int x)
{
bool p=,q=;
for(int i=head[x];i;i=e[i].pre)
if(e[i].v!=fa[x][])
{
color(e[i].v);p&=vis[e[i].v];q=;
}
if(p&&q&&x!=)vis[x]=;
}
bool check(int x)
{
memset(vis,,sizeof(vis));
int cnt=,tot=;
for(int i=;i<=m;i++)
{
int y=pos[i],z=;
for(int j=;j>=;j--)//尽量向上跑
if(fa[y][j]&&z+dis[y][j]<=x)
{
z+=dis[y][j];
y=fa[y][j];
}
if(y!=)vis[y]=;//跑不到根节点
else//能跑到根节点,求出b结构体
{
b[++cnt].v=x-z;
y=pos[i];
for(int j=;j>=;j--)
if(fa[y][j]>)
y=fa[y][j];
b[cnt].u=y;
}
}
color();//处理跑不到根节点的点
for(int i=head[];i;i=e[i].pre)//找根节点的子节点
if(!vis[e[i].v])
{
c[++tot].u=e[i].v;
c[tot].v=e[i].t;
}
sort(b+,b+cnt+,cmp);
sort(c+,c+tot+,cmp);
int j=;
for(int i=;i<=cnt;i++)//匹配
{
if(!vis[b[i].u])vis[b[i].u]=;
else if(b[i].v>=c[j].v)vis[c[j].u]=;
while(vis[c[j].u]&&j<=tot)j++;
}
return j>tot;
}
int main()
{
n=read();
int ll=,rr=;
for(int i=;i<n;i++)
{
int x=read(),y=read(),z=read();
add(i*-,x,y,z);add(i*,y,x,z);
rr+=z;
}
m=read();
for(int i=;i<=m;i++)
pos[i]=read();
dfs(,);//深搜记录父亲结点,边权值
get_fa();//DP求出倍增用到的节点和权值
while(ll<=rr)//二分答案
{
int mid=(ll+rr)/;
if(check(mid))rr=mid-;
else ll=mid+;
}
if(check(ll))printf("%d",ll);
else printf("-1");
return ;
}

疫情控制(codevs 1218)的更多相关文章

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

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

  2. 【NOIP2012】 疫情控制

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

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

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

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

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

  5. 疫情控制 blockade

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

  6. codevs1218 疫情控制

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

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

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

  8. CH6301 疫情控制

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

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

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

随机推荐

  1. SP2916 GSS5 - Can you answer these queries V

    给定一个序列.查询左端点在$[x_1, y_1]$之间,且右端点在$[x_2, y_2]$之间的最大子段和,数据保证$x_1\leq x_2,y_1\leq y_2$,但是不保证端点所在的区间不重合 ...

  2. 简单几何(水)BestCoder Round #50 (div.2) 1002 Run

    题目传送门 /* 好吧,我不是地球人,这题只要判断正方形就行了,正三角形和正五边形和正六边形都不可能(点是整数). 但是,如果不是整数,那么该怎么做呢?是否就此开启计算几何专题了呢 */ /***** ...

  3. 图论 HDOJ 5348 MZL's endless loop

    题目传送门 /* 题意:给一个n个点,m条边的无向图,要求给m条边定方向,使得每个定点的出入度之差的绝对值小于等于1. 输出任意一种结果 图论:一个图,必定存在偶数个奇度顶点.那么从一个奇度定点深搜, ...

  4. 410 Split Array Largest Sum 分割数组的最大值

    给定一个非负整数数组和一个整数 m,你需要将这个数组分成 m 个非空的连续子数组.设计一个算法使得这 m 个子数组各自和的最大值最小.注意:数组长度 n 满足以下条件:    1 ≤ n ≤ 1000 ...

  5. PostgreSQL与MySQL比较

    特性 MySQL PostgreSQL 实例 通过执行 MySQL 命令(mysqld)启动实例.一个实例可以管理一个或多个数据库.一台服务器可以运行多个 mysqld 实例.一个实例管理器可以监视 ...

  6. linux下jdk与tomcat的安装与配置

    Linux中jdk与tomcat的安装与配置 1.搭建环境: (1)Linux环境:CentOS6.1 (2)jdk-1.8 (3)tomcat-9.0 2.在Linux系统上创建目录 在usr/lo ...

  7. [ NOI 2002 ] Robot

    \(\\\) Description \(\\\) Solution 垃圾语文题毁我青春 这题其实就是重定义了俩函数.... 首先 \(\varphi(1)=0\) . 然后 \(2\) 在计算 \( ...

  8. Windows下80端口被进程System&PID=4占用的解决方法

    我的占用原因是 SQL Server Reporting Services,停止掉这个服务并设置其为手动启动即可 如果你并没有安装 SQL Server,请参考下文解决 =============== ...

  9. JS高级——弹出框的美化

    替换原有的alert方法,window.alert=function(){} https://blog.csdn.net/kirsten_z/article/details/76242286 http ...

  10. Python orm基础

    ORM 对象映射关系程序. 通过orm将编程语言的对象模型和数据库的关系模型建立映射关系,这样我们在使用编程语言对数据库进行操作的时候可以直接使用编程语言的对象模型进行操作就可以了,而不用直接使用sq ...