题目描述

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

也是树中的根节点。

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

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

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

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

现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在

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

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

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

输入输出格式

输入格式:

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

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

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

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

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

的城市的编号。

输出格式:

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

输入输出样例

输入样例#1:

4
1 2 1
1 3 2
3 4 3
2
2 2
输出样例#1:

3

说明

【输入输出样例说明】

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

NOIP 2012 提高组 第二天 第三题

二分答案,看能否全部覆盖。

在限定的时间内,所有军队全速向首都行进。无法到达首都的军队要驻扎在尽可能近的位置(以尽可能控制更多边缘城市),能到达首都的军队,要根据其剩余时间选择支援哪个城市(只要走到首都的第一层子结点就能控制其下的所有边缘城市),或者选择干脆不到达首都,直接驻扎在其来路的离首都最近城市。

↑以上操作可以用LCA便捷实现。

将所有可用军队的剩余时间从小到大排序,将所有需要支援结点的距离从小到大排序,贪心选择军队去支援即可。

↑但要注意,如果一支军队的剩余时间特别少,而它来路到首都的距离特别长,那么应该让它干脆不到达首都。具体实现看代码:

(我也不知道我为什么写了这么长)

 /*by SilverN*/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define fou(x,i,j) for(int x=i;x<=j;++x)
#define fo(x,i,j) for(int x=i;x>=j;--x)
using namespace std;
const int mxn=;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
LL readL(){
LL x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
struct edge{
int v,nxt;
LL dis;
}e[mxn<<];
int hd[mxn],mct=;
void add_edge(int u,int v,LL dis){
e[++mct].v=v;e[mct].nxt=hd[u];e[mct].dis=dis;hd[u]=mct;
return;
}
//
int n,m;
int pos[mxn];
//
int dep[mxn];
LL dis[mxn];
int fa[mxn][];
void DFS(int u,int ff){
dep[u]=dep[ff]+;
for(int i=hd[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==ff)continue;
fa[v][]=u;
dis[v]=dis[u]+e[i].dis;
DFS(v,u);
}
return;
}
void LCA_init(){
fou(i,,)
fou(j,,n)
fa[j][i]=fa[fa[j][i-]][i-];
return;
}
struct cme{
int come;
LL dis;
}ari[mxn];//上溯时间
int cnt;
int cmp1(const cme a,const cme b){return a.dis<b.dis;}
struct tpro{
int city,dis;
}c[mxn];
int cmp2(const tpro a,const tpro b){return a.dis<b.dis;}
int cct=;
//
int nps[mxn];
bool pro[mxn];//受保护的城市
void find(int u,int ff){
if(!e[hd[u]].nxt)return;
bool flag=;
for(int i=hd[u];i;i=e[i].nxt){
int v=e[i].v;
if(v==ff)continue;
// printf("u %d to %d %d\n",u,v,pro[v]);
if(pro[v]){continue;}
find(v,u);
if(!pro[v])flag=;
}
pro[u]=flag;
return;
} bool solve(LL lim){
// printf("\n\ntest lim:%d\n",lim);
memset(pro,,sizeof pro);
memset(ari,,sizeof ari);
memcpy(nps,pos,sizeof pos);
cnt=;cct=;
for(int i=;i<=m;i++){
if(dis[nps[i]]>lim){//时间不够回到首都
LL lft=dis[nps[i]]-lim;
// printf("%d left:%d\n",i,lft);
fo(j,,)
if(dis[fa[nps[i]][j]]>=lft)
nps[i]=fa[nps[i]][j];
pro[nps[i]]=;
// printf("num %d protected %d\n",i,nps[i]);
}
else{//时间够回到首都
ari[++cnt].dis=lim-dis[nps[i]];
fo(j,,){
// printf("%d %d %d\n",fa[nps[i]][j],dep[fa[nps[i]][j]],nps[i]);
if(dep[fa[nps[i]][j]]>)nps[i]=fa[nps[i]][j];
}
ari[cnt].come=nps[i];
// printf("%d comes from :%d\n",i,nps[i]);
}
}
find(,);
// printf("fin1\n");
if(pro[])return true;
// printf("nxt:\n");
for(int i=hd[];i;i=e[i].nxt){
int v=e[i].v;
if(!pro[v]) c[++cct].city=v,c[cct].dis=e[i].dis;
}
sort(ari+,ari+cnt+,cmp1);
sort(c+,c+cct+,cmp2);
/* printf("tpro:\n");
for(int i=1;i<=cct;i++){
printf("%d ",c[i].city);
}
printf("\n");*/
int j=;
for(int i=;i<=cnt;i++){
if(!pro[ari[i].come]){
pro[ari[i].come]=;
continue;
}
while(pro[c[j].city] && j<=cct)j++;
if(c[j].dis<=ari[i].dis)pro[c[j].city]=,++j;
}
for(int i=;i<=cct;i++){
if(!pro[c[i].city])return false;
}
return true;
}
LL ans=1e11;
int main(){
n=read();
int i,j,u,v,w;
LL smm=;
for(i=;i<n;++i){
u=read();v=read();w=readL();
add_edge(u,v,w);
add_edge(v,u,w);
smm+=w;
}
DFS(,);
LCA_init();
m=read();
for(i=;i<=m;++i)pos[i]=read();
LL l=,r=smm;
while(l<=r){
LL mid=(l+r)>>;
if(solve(mid)){
ans=mid;
r=mid-;
}
else l=mid+;
}
if(ans==1e11){printf("-1\n");}
else printf("%lld\n",ans);
return ;
}

[NOIP2012] 提高组 洛谷P1084 疫情控制的更多相关文章

  1. 洛谷P1084 疫情控制(NOIP2012)(二分答案,贪心,树形DP)

    洛谷题目传送门 费了几个小时杠掉此题,如果不是那水水的数据的话,跟列队的难度真的是有得一比... 话说蒟蒻仔细翻了所有的题解,发现巨佬写的都是倍增,复杂度是\(O(n\log n\log nw)\)的 ...

  2. [NOIP2012] 提高组 洛谷P1081 开车旅行

    题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 ...

  3. [NOIP2012] 提高组 洛谷P1080 国王游戏

    题目描述 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右 手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排 成一排,国王站在队伍 ...

  4. [NOIP2012] 提高组 洛谷P1083 借教室

    题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自然 ...

  5. [NOIP2012] 提高组 洛谷P1082 同余方程

    题目描述 求关于 x 的同余方程 ax ≡ 1 (mod b)的最小正整数解. 输入输出格式 输入格式: 输入只有一行,包含两个正整数 a, b,用一个空格隔开. 输出格式: 输出只有一行,包含一个正 ...

  6. [NOIP2012] 提高组 洛谷P1079 Vigenère 密码

    题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法――Vigenère 密 码.Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国南 ...

  7. NOIP2012 洛谷P1084 疫情控制

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

  8. 洛谷P1084 疫情控制 [noip2012] 贪心+树论+二分答案 (还有个小bugQAQ

    正解:贪心+倍增+二分答案 解题报告: 正好想做noip的题目然后又想落实学长之前讲的题?于是就找上了这题 其实之前做过,70,然后实在细节太多太复杂就不了了之,现在再看一遍感觉又一脸懵了... 从标 ...

  9. 洛谷 P1084 疫情控制 —— 二分+码力

    题目:https://www.luogu.org/problemnew/show/P1084 5个月前曾经写过一次,某个上学日的深夜,精疲力竭后只有区区10分,从此没管... #include< ...

随机推荐

  1. 乐易贵宾VIP教程:百度贴吧 - QQ部落 - QQ空间 Post实战系列视频课程

    教程挺不错,3套案例的实战,有需要的可以看一下百度贴吧课程目录:1.百度登录抓包分析2.百度登录[代码实现]3.百度验证码登录[代码实现]4.贴吧关注[抓包分析]5.贴吧关注(代码编写)6.贴吧签到[ ...

  2. 漫谈 Java 实例化类

    Java 中实例化类的动作,你是否还是一成不变 new 对应对象呢? 经手的项目多了,代码编写量自然会增加,渐渐的会对设计模式产生感觉. 怎样使书写出来的类实例化动作,高内聚,低耦合,又兼具一定的扩展 ...

  3. 使用Redis做预定库存缓存功能

    最近在自己的工作中,把其中一个PHP项目的缓存从以前的APC缓存逐渐切换到Redis中,并且根据Redis所支持的数据结构做了库存维护功能.缓存是在业务层做的,准确讲应该是在MVC模型中Model的O ...

  4. WebApiTestClient自定义返回值说明

    WebApiTestClient是基于微软HelpPage一个客户端调试扩展工具,用来做接口调试比较方便.但是对返回值的自定义说明还是有缺陷的.有园友写过一篇文章,说可以通过对类进行注释,然后通过在I ...

  5. hihocoder [Offer收割]编程练习赛4

    描述 最近天气炎热,小Ho天天宅在家里叫外卖.他常吃的一家餐馆一共有N道菜品,价格分别是A1, A2, ... AN元.并且如果消费总计满X元,还能享受优惠.小Ho是一个不薅羊毛不舒服斯基的人,他希望 ...

  6. apache 多端口配置和虚拟主机配置

    1 打开httpd.conf文件 2 添加端口监听 (找到Lisen 80 在后面添加 Listen 端口号 如Listen 1112) port =>你的端口 project_name=> ...

  7. SWIFT--文档地址

    APPLE官方: https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/Swift ...

  8. chrome编辑DOM

    来源于:https://developers.google.com/web/tools/chrome-devtools/inspect-styles/edit-dom The DOM tree vie ...

  9. Java--剑指offer(8)

    36.输入两个链表,找出它们的第一个公共结点. 解题思路:这里主要是把两个链表的节点都放入两个栈中,这样就可以按照出栈的方式来比较节点,因为单链表只要是有相同的节点,那么之后的节点也都是一样的,所以如 ...

  10. jQuery基础--样式篇(5)

    jQuery的属性与样式 (1).attr()与.removeAttr():每个元素都有一个或者多个特性,这些特性的用途就是给出相应元素或者其内容的附加信息. attr()有4个表达式 attr(传入 ...