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

时间限制: 2 s

空间限制: 128000 KB

题目等级 : 钻石 Diamond

题目描述 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

/*
这题太好了!!!
二分+lca+贪心策略.
二分[1,∑w].
先dfs序+lca处理出各点关系.
然后二分检验.
贪心策略:
(1)向上走更优.
(2)排序后能最大匹配.
我们先来考虑几种情况
(1)这个军队能够蹦到根节点.
我们处理出蹦到根节点后剩余的时间.
(2)这个军队蹦不到根节点
我们尽量让他往上蹦.
然后向上传标记.
最后只需要扫根节点的儿子就可以了.
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 50001
#define D 20
using namespace std;
int fa[MAXN][D+5],deep[MAXN],son[MAXN],head[MAXN],n,m,dis[MAXN],a[MAXN],tot,ans=1e9,top,cut,sum;
bool b[MAXN];
struct data{int v,u;}s[MAXN],c[MAXN];
struct egde{int v,next,x;}e[MAXN*2];
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*f;
}
void add(int u,int v,int z)
{
e[++tot].v=v;
e[tot].x=z;
e[tot].next=head[u];
head[u]=tot;
}
bool cmp(const data &x,const data &y)
{
return x.v<y.v;
}
void dfs(int now,int father,int d)
{
fa[now][0]=father;
for(int i=head[now];i;i=e[i].next)
{
if(father!=e[i].v)
{
dis[e[i].v]=dis[now]+e[i].x;
dfs(e[i].v,now,d+1);
}
}
}
void get_father()
{
for(int j=1;j<=20;j++)
for(int i=1;i<=n;i++)
fa[i][j]=fa[fa[i][j-1]][j-1];
}
void slove(int u,int fa)
{
bool flag=false,p=1;
for(int i=head[u];i;i=e[i].next)
{
int v=e[i].v;
if(fa!=v)
slove(v,u),p&=b[v],flag=true;
}
if(flag&&p&&u!=1) b[u]=true;return ;
}
bool check(int x)
{
memset(b,0,sizeof(b));
int father=0;top=0,cut=0;
for(int i=1;i<=m;i++)
{
int now=a[i],d=0;
if(dis[now]<x)
father=1;
else for(int j=20;j>=0;j--)
{
if(fa[now][j]&&dis[now]-dis[fa[now][j]]<=x)
{
father=fa[now][j];
d=dis[now]-dis[fa[now][j]];
break;
}
}
if(father!=1) b[father]=true;
else
{
s[++top].v=x-dis[now];
for(int j=20;j>=0;j--)
if(fa[now][j]>1)
now=fa[now][j];
s[top].u=now;
}
}
slove(1,0);
for(int i=head[1];i;i=e[i].next)
if(!b[e[i].v])
c[++cut].u=e[i].v,c[cut].v=e[i].x;
sort(s+1,s+top+1,cmp),sort(c+1,c+cut+1,cmp);
int j=1;c[cut+1].v=1e9;
for(int i=1;i<=top;i++)
{
if(!b[s[i].u]) b[s[i].u]=true;
else if(s[i].v>=c[j].v) b[c[j].u]=true;
while(b[c[j].u]) j++;
}
return j>cut;
}
void erfen(int ll,int rr)
{
int mid;
while(ll<=rr)
{
mid=(ll+rr)>>1;
if(check(mid)) ans=mid,rr=mid-1;
else ll=mid+1;
}
}
int main()
{
int x,y,z;
n=read();
for(int i=1;i<n;i++)
{
x=read(),y=read();z=read();
add(x,y,z);sum+=z;add(y,x,z);
}
m=read();
for(int i=1;i<=m;i++)
a[i]=read();
dfs(1,0,0);
get_father();
erfen(1,sum);
if(ans==1e9) printf("-1");
else printf("%d\n",ans);
return 0;
}

Codevs 1218 疫情控制 2012年NOIP全国联赛提高组的更多相关文章

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

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

  2. Codevs 1217 借教室 2012年NOIP全国联赛提高组

    1217 借教室 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 在大学期间,经常需要租借教 ...

  3. Codevs 1198 国王游戏 2012年NOIP全国联赛提高组

    1198 国王游戏 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 恰逢 H 国国庆,国王邀 ...

  4. Codevs 1200 同余方程 2012年NOIP全国联赛提高组

    1200 同余方程 2012年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description 求关于 x 同余方程 a ...

  5. 开车旅行 2012年NOIP全国联赛提高组(倍增+set)

    开车旅行 2012年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond     题目描述 Description 小A 和小B决定利用 ...

  6. Codevs 3286 火柴排队 2013年NOIP全国联赛提高组 树状数组,逆序对

    题目:http://codevs.cn/problem/3286/ 3286 火柴排队  2013年NOIP全国联赛提高组  时间限制: 1 s   空间限制: 128000 KB   题目等级 : ...

  7. Codevs 1069 关押罪犯 2010年NOIP全国联赛提高组

    1069 关押罪犯 2010年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description S 城现有两座监狱,一共 ...

  8. Codevs 3731 寻找道路 2014年 NOIP全国联赛提高组

    3731 寻找道路 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题目描述 Description 在有向图G中,每条边的长度均为1,现给定起点和终点,请你在图中找 ...

  9. Codevs 3287 货车运输 2013年NOIP全国联赛提高组(带权LCA+并查集+最大生成树)

    3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description A 国有 n 座 ...

随机推荐

  1. 【转】来自《轻松scrum之旅》的敏捷开发总结

    敏捷开发的核心价值观是,软件开发最重要的是给用户提供有价值的.可以工作的软件.如何保证提供有价值的软件,是通过反馈机制来完成的.这一点,我们体会很深.自从采用敏捷开发以后,我们比以前更有意识地希望得到 ...

  2. 【M12】了解“抛出一个exception”与“传递一个参数”或“调用一个虚函数”之间的差异

    1.方法参数的声明语法和catch语句的语法是一样的,你可能会认为主调方法调用一个方法,并向其传递参数,与抛出一个异常传递到catch语句是一样的,是的,有相同之处,但也有更大的不同. 2.主调方法调 ...

  3. 【转】C++对象内存分配问题

    原文:http://blog.csdn.net/c504665913/article/details/7797859 如果一个人自称为程序高手,却对内存一无所知,那么我可以告诉你,他一定在吹牛.用C或 ...

  4. Linux下修改网卡IP、DNS和网关

    Linux下修改网卡IP和网关 建议通过终端字符方式下来修改 一.修改IP地址 vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 BOO ...

  5. [JavaScript]'this'详解

    http://blog.csdn.net/sodino/article/details/51318565

  6. [Effective C++ --016]成对使用New和Delete时要采用相同形式

    这一节比较简单,可以总结为以下: std::string *stringPtr1 = new std::string; std::]; .. delete stringPtr1; // delete ...

  7. Linux下用dump实现备份和还原 ux下用dump实现备份和还原

    对于系统而言,我们可以有很多种办法去备份(还原)系统或文件,之所以要去做备份,就是为了在系统或文件遭到损害时,能及时恢复,把损失减小到最小.当然,对于企业服务器而言,备份的重要性是举足轻重.咱们今天就 ...

  8. 【转】在XCode工程中创建bundle包

    http://www.giser.net/?p=859 Bundle Programming Guide: https://developer.apple.com/library/ios/docume ...

  9. 分享一个字数限制和统计的UITextView分类方法

    - (NSUInteger)letterCountWithLimits:(NSInteger)limits { NSString *toBeString = self.text; NSUInteger ...

  10. mfc模态对话框

    Mfc模态对话框: 创建模态对话框: [模态对话框:具有独占行为,必须由用户完成对当前对话框的响应,才能对本对话框所属的进程进行其他操作] 例如: 我们创建一个加法计算器.点击计算之后,弹出一个对话框 ...