题目:

题目背景

NOIP2012 提高组 DAY2 试题。

题目描述

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

H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是,首都是不能建立检查点的。

现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等于道路的长度(单位:小时)。

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

输入格式

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

输出格式

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

样例数据 1

输入  [复制]

 


1 2 1 
1 3 2 
3 4 3 

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。

题解:

贪心的妙用····表示一道题先根据题意找到基本策略真的很重要

首先要明白,将军队在不超时的情况下往根节点移动越多控制的叶子节点肯定是越多的。

因此先二分答案,然后在答案的限制下尽量将所有军队往根节点移动(因为一个军队越靠近根节点控制的叶节点肯定越多)

然后通过递归(注意这里递归是如果一个节点的所有儿子都被军队占领了,相当于它一个节点被占领,这样递归从叶子节点到根节点层层染色)找到根节点(1号)的哪些儿子还需要军队来占领(因为如果根节点的儿子还未被占领,则儿子所在子树的叶子节点肯定还未被控制)

于是那些移动得到根节点的军队就有用处了···首先,如果一个军队在移动到根节点的过程中经过了这些还未被占领的儿子节点中的一个,则用这个军队占领这个儿子节点即可.如果不是,将它们派去占领其他儿子节点(注意这里又会用到一次贪心,将移动到根节点后剩余时间少的军队尽量去占领那些与根节点距离小的儿子节点,总体下来无疑会占领得更多)。

这样的话所算出的占领叶子节点数一定是最多的

没想到这道题考贪心会考这么深···

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=5e4+;
int Rint()
{
char c;
int f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar())
f=(f<<)+(f<<)+c-'';
return f;
}
long long Rlong()
{
char c;
long long f=;
for(c=getchar();c<''||c>'';c=getchar());
for(;c<=''&&c>='';c=getchar())
f=(f<<)+(f<<)+c-'';
return f;
}
struct node
{
int point;
long long dis;
}army[N],leftcity[N];
bool visit[N];
bool comp(node x,node y)
{
return x.dis<y.dis;
}
int first[N],next[N*],go[N*],tot,a[N];
long long val[N*],dis[N][];
int n,m,g[N][],deep[N],tota,totl;
void comb(int a,int b,long long c)
{
next[++tot]=first[a],first[a]=tot,go[tot]=b,val[tot]=c;
next[++tot]=first[b],first[b]=tot,go[tot]=a,val[tot]=c;
}
inline void dfs(int u,int fa)
{
for(int e=first[u];e;e=next[e])
{
int v=go[e];
if(v==fa) continue;
g[v][]=u;
deep[v]=deep[u]+;
dis[v][]=val[e];
dfs(v,u);
}
}
inline void color(int u)
{
int t1=,t2=;
for(int e=first[u];e;e=next[e])
{
int v=go[e];
if(v==g[u][]) continue;
color(v);
if(!visit[v]) t1=;
else t2=;
}
if(t1==&&t2==&&u!=) visit[u]=true;
}
inline bool check(long long limit)
{
memset(visit,false,sizeof(visit));
tota=,totl=;
for(int i=;i<=m;i++)
{
long long temp=limit;
int u=a[i];
for(int j=;j>=;j--)
{
if(g[u][j]>=&&temp>=dis[u][j])
{
temp-=dis[u][j];
u=g[u][j];
if(u==)
break;
}
}
if(u!=) visit[u]=true;
else
{
army[++tota].dis=temp;
u=a[i];
for(int j=;j>=;j--)
if(g[u][j]>) u=g[u][j];
army[tota].point=u;
}
}
color();
for(int e=first[];e;e=next[e])
{
if(!visit[go[e]])
{
leftcity[++totl].point=go[e];
leftcity[totl].dis=val[e];
}
}
sort(leftcity+,leftcity+totl+,comp);
sort(army+,army+tota+,comp);
leftcity[totl+].dis=1e+;
int head=;
for(int i=;i<=tota;i++)
{
if(!visit[army[i].point])
visit[army[i].point]=true;
else
{
if(army[i].dis>=leftcity[head].dis)
visit[leftcity[head].point]=true;
}
while(visit[leftcity[head].point]==true)
{
head++;
if(head>totl)
return true;
}
}
return false;
}
int main()
{
//freopen("a.in","r",stdin);
n=Rint();
int A,B;
long long C;
long long left=,right=;
for(int i=;i<n;i++)
{
A=Rint(),B=Rint(),C=Rlong();
comb(A,B,C);
right+=C;
}
m=Rint();
dfs(,);
for(int i=;i<=m;i++) a[i]=Rint();
for(int i=;i<=;i++)
for(int j=;j<=n;j++)
{
g[j][i]=g[g[j][i-]][i-];
dis[j][i]=dis[j][i-]+dis[g[j][i-]][i-];
}
while(left<right)
{
long long mid=(left+right)/;
if(check(mid)) right=mid;
else left=mid+;
}
if(check(left)) cout<<left<<endl;
else cout<<"-1"<<endl;
return ;
}

刷题总结——疫情控制(NOIP2012提高组)的更多相关文章

  1. 刷题总结——子串(NOIP2015提高组)

    题目: 题目背景 NOIP2015 提高组 Day2 T2 题目描述 有两个仅包含小写英文字母的字符串 A 和 B .现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在 ...

  2. 【未完成0.0】Noip2012提高组day2 解题报告

    第一次写一套题的解题报告,感觉会比较长.(更新中Loading....):) 题目: 第一题:同余方程 描述 求关于x的同余方程ax ≡ 1 (mod b)的最小正整数解. 格式 输入格式 输入只有一 ...

  3. GZOJ 1361. 国王游戏【NOIP2012提高组DAY1】

    国王游戏[NOIP2012提高组DAY1] Time Limit:1000MS Memory Limit:128000K Description 国王游戏(game.cpp/c/pas) [问题描述] ...

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 异步 ThreadPool

    线程池是单例,一个进程里只有一个线程池 private void btnThreadPool_Click(object sender, EventArgs e) { Stopwatch watch = ...

  2. OC 导入类 #import和@class 区别

    objective-c中#import和@class的区别 在Objective-C中,可以使用#import和@class来引用别的类型, 但是你知道两者有什么区别吗? @class叫做forwar ...

  3. js 判断是什么浏览器、是否为谷歌浏览器

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta http ...

  4. WPF中在后台实现控件样式

    加入现在有一个Button的样式如下: <Style TargetType="{x:Type Button}" x:Key="MyButton">. ...

  5. python在d盘,robotframework引入seleniumlibrary报错

    在*** setting*** 中引入库   Library  SeleniumLibrary  报错 unknown seleniumlibrary library ,try to use quic ...

  6. 稳定性 耗时 gc 过长问题排查 和工具

    自己的另外一篇: http://www.cnblogs.com/fei33423/p/7805186.html 偶有耗时抖动? gc 也有长耗时? fullgc 也是? 有同学反馈 swap 可能导致 ...

  7. Fortran学习笔记2(变量声明)

    常数的申明方式 变量初始化 等价申明EQUIALENCE 类型转化 自定义类型 KIND用法 常数的申明方式 程序中所有处理的数据,有些事固定不变的常数,如圆周率π和重力加速度G等. 此时,程序员可以 ...

  8. Bzoj3170: [Tjoi2013]松鼠聚会 (切比雪夫距离)

    题目链接 显然,题目要求我们求切比雪夫距离,不会的可以去看一下attack的博客. 考虑枚举所有的点 转换为曼哈顿距离后. 那么对于这个点的路程和是. \[\sum_{i=1}^n | x_i - x ...

  9. vue2.0的基本特性

    本文目前总结的特性如下1.侦听属性和计算属性2.class的绑定3.条件渲染时的注意事项4.v-if和v-for同时使用的注意事项5.插槽6.ref,父组件调用子组件的另一种方式7.<keep- ...

  10. (转)iOS开发之同一应用设置不同图标和名称

    本文转自:http://www.devzeng.com/blog/ios-two-version-app-setting-profile.html iOS开发之同一应用设置不同图标和名称 SEP 6T ...