刷题总结——疫情控制(NOIP2012提高组)
题目:
题目背景
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
备注
【样例说明】
第一支军队在 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提高组)的更多相关文章
- 刷题总结——子串(NOIP2015提高组)
题目: 题目背景 NOIP2015 提高组 Day2 T2 题目描述 有两个仅包含小写英文字母的字符串 A 和 B .现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在 ...
- 【未完成0.0】Noip2012提高组day2 解题报告
第一次写一套题的解题报告,感觉会比较长.(更新中Loading....):) 题目: 第一题:同余方程 描述 求关于x的同余方程ax ≡ 1 (mod b)的最小正整数解. 格式 输入格式 输入只有一 ...
- GZOJ 1361. 国王游戏【NOIP2012提高组DAY1】
国王游戏[NOIP2012提高组DAY1] Time Limit:1000MS Memory Limit:128000K Description 国王游戏(game.cpp/c/pas) [问题描述] ...
- [NOIP2012] 提高组 洛谷P1084 疫情控制
题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都, 也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散 ...
- 洛谷P1084 [NOIP2012提高组Day2T3]疫情控制
P1084 疫情控制 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控 ...
- [NOIP2012] 提高组 洛谷P1081 开车旅行
题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 ...
- [NOIP2012] 提高组 洛谷P1080 国王游戏
题目描述 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右 手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排 成一排,国王站在队伍 ...
- [NOIP2012] 提高组 洛谷P1083 借教室
题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自然 ...
- [NOIP2012] 提高组 洛谷P1082 同余方程
题目描述 求关于 x 的同余方程 ax ≡ 1 (mod b)的最小正整数解. 输入输出格式 输入格式: 输入只有一行,包含两个正整数 a, b,用一个空格隔开. 输出格式: 输出只有一行,包含一个正 ...
随机推荐
- Azure School女神相邀,把每分钟都过的更充实
也许你不姓「牛」,但是你技术牛啊 所以,请容我叫你一声「牛郎」 (讲真,只是因为你技术牛,不是其他啥原因哈) 平时忙到昏天黑地,一心一意为技术的你 注意看一下日历,因为: !!!七夕节(8月28日)到 ...
- IOS修改系统音量
#import <IOKit/IOKitLib.h> #import <IOKit/hidsystem/IOHIDLib.h> #import <IOKit/hidsys ...
- Ubuntu 18.04 上使用 OpenJDK 安装并运行 Tomcat
在Linux上安装与卸载JDK和JRE,两种常用方法: 一.通过 apt-get 命令在线进行安装与卸载(会自动配置好环境变量) 二.通过下载并解压 .tar.gz 包进行手动安装与手动卸载(需要手动 ...
- servlet多文件上传(带进度条)
需要commons-fileupload-1.3.jar和commons-io-2.4.jar的支持 页面效果:(图片文件都可以) (1)进度标识类 public class UploadStatus ...
- ueditor中FileUtils.getTempDirectory()找不到
2014-6-27 14:22:25 org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() fo ...
- bootstrap下拉菜单(Dropdowns)
本章将重点讲解bootstrap下拉菜单(Dropdowns),下拉菜单是可切换的,是以列表格式显示链接的上下文菜单. <!DOCTYPE html><html><hea ...
- Codeforces Round #477滚粗记&&祭第一次div2场
4.29 - 23:58:现在似乎在ST的样子……先等一波 Day4.29 prescript : 难得遇上一场9:00开始的div2,看了看大家都打,索性也当一回神仙吧. 晚上出去吃饭,匆匆赶回家, ...
- PHP 把字符转换为 HTML 实体 - htmlentities() 函数
定义和用法 htmlentities() 函数把字符转换为 HTML 实体. 语法 htmlentities(string,quotestyle,character-set) 参数 描述 string ...
- 【OS_Linux】Linux下软件的安装与卸载
1.Linux中软件安装包的分类 1) 一类是可执行的软件包,无需编译直接安装.在Windows中所有的软件包都是这种类型.安装完这个程序后,你就可以使用,但你看不到源程序.而且下载时要注意这个软件是 ...
- Shell脚本的条件测试与比较
Shell脚本的条件测试与比较 一.shell脚本的条件测试 通常,在bash的各种条件结构和流程控制结构中都要进行各种测试,然后根据测试结构执行不同的操作,有时也会与if等条件语句相结合,来完成测试 ...