【NOIP2012】疫情传递
题解
这题是真的烦。。。
越来越心疼2012年的dalao们了【不过好像dalao们都不需要本蒟蒻的心疼2333】
其实这题还有点半懂不懂。。。
所以把洛谷上一个比较好的题解粘过来记忆一下233
1.预处理倍增
我们会发现,离根节点越近的节点,控制的节点更多。所以由贪心的思想,所有的军队都要尽可能地往根节点走。
> ”往上提“类型问题一般使用倍增优化。——xzy神犇
xzy神犇的博客:k-xzy.cf
好大的,那么我们可以dfs一遍,将倍增要用的一些值都处理好(见代码)
2.二分答案
军队可以同时移动,说明我们要控制传染病的时间是军队移动到位时,移动时间最长的军队的移动时间。而我们要求最小值,即要求最大化最小值。
> 二分答案一般用于求最大化最小值,最小化最大值。——jyf神犇
所以就是二分啦,二分一个答案,事情就会更有方向。
3.”上提“军队
使用倍增的方法将军队在二分出的答案限制内尽力往上”提“,不过不可以到根节点。
4.处理剩余路程
如果当前军队可以到达根节点,那么记录一下它的编号和它到达根节点后还可以走的时间rest。如果这个军队i在根节点的子树x中,那么记录一下子树x的符合这个条件的点中,到根节点后剩余路程最短的点。
如果不可以到达,记录它被”提“到的节点被军队设置了检查点。
5.dfs找未被”封死“的子树
如果一个节点建立了检查点或者它的所有子树都设立了检查点,则说明以这个节点为根的子树已经被“封死”。记录根节点的所有子树中,未被“封死”的子树。
6.军队在子树间转移
将我们已经记录好了的可以到根节点的军队按照剩余路程从大到小排序。
将未被“封死”的子树按照到子树到根节点的距离从大到小排序。
然后依次处理未被“封死”的子树要由哪支军队来管辖。
当然离根节点远的军队由剩余路程大的军队来管辖是吼滴啦,不过缀吼滴还是就由本来就在这棵子树上的军队来管辖。所以我们先查看我们事先记录的(在子树x中,可以到达根节点,且到根节点后剩余路程最小的军队)是否被使用,如果被使用,再看当前没有被使用的军队里剩余路程最大的可否到达这棵子树。
这样我们就可以判断当前二分出的答案是否可行了。
来自某dalao——litble
代码
//by 减维
#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<map>
#include<algorithm>
#define ll long long
using namespace std; struct edge{
int to,ne;
ll v;
}e[]; struct res{
int po;
ll v;
}rest1[],rest2[]; ll maxroad,fv[][],mp[],mv[];
int n,m,num1,num2,ecnt,pos[],head[],f[][];
bool used[],vis[]; bool cmp(const res&x,const res&y){return x.v>y.v;} void add(int x,int y,ll z)
{
e[++ecnt].to=y;
e[ecnt].v=z;
e[ecnt].ne=head[x];
head[x]=ecnt;
} void dfs(int x)
{
for(int i=head[x];i;i=e[i].ne)
{
int dd=e[i].to;
if(dd==f[x][])return ;
f[dd][]=x;
fv[dd][]=e[i].v;
dfs(dd);
}
} void beizeng()
{
for(int j=;j<=;++j)
for(int i=;i<=n;++i)
{
f[i][j]=f[f[i][j-]][j-];
fv[i][j]=fv[i][j-]+fv[f[i][j-]][j-];
}
} bool find(int x)
{
bool fl=,ok=;
if(vis[x])return ;
for(int i=head[x];i;i=e[i].ne)
{
int dd=e[i].to;
if(dd==f[x][])continue;
ok=;
if(!find(dd)){
fl=;
if(x==)rest2[++num2].po=dd,rest2[num2].v=e[i].v;
else return ;
}
}
if(!ok)return ;
return fl;
} bool check(ll mid)
{
for(int i=;i<=n;++i)vis[i]=mp[i]=;
for(int i=;i<=m;++i)used[i]=;
num1=,num2=;
for(int i=;i<=m;++i)
{
int x=pos[i];ll dis=;
for(int j=;j>=;--j)
if(f[x][j]>&&dis+fv[x][j]<=mid)
dis+=fv[x][j],x=f[x][j];
if(f[x][]==&&dis+fv[x][]<=mid){
rest1[++num1].po=i,rest1[num1].v=mid-dis-fv[x][];
if(!mp[x]||rest1[num1].v<mv[x])
mv[x]=rest1[num1].v,mp[x]=i;
}
else vis[x]=;
}
if(find())return ;
sort(rest1+,rest1+num1+,cmp);
sort(rest2+,rest2+num2+,cmp);
int num=;
used[]=;
for(int i=;i<=num2;++i)
{
if(!used[mp[rest2[i].po]]){used[mp[rest2[i].po]]=;continue;}
while(num<=num1&&(used[rest1[num].po]||rest1[num].v<rest2[i].v))num++;
if(num>num1)return ;
used[rest1[num].po]=;
}
return ;
} int main()
{
scanf("%d",&n);
for(int i=;i<n;++i)
{
int x,y;ll z;
scanf("%d%d%lld",&x,&y,&z);
add(x,y,z);
add(y,x,z);
maxroad+=z;
}
dfs();
beizeng();
scanf("%d",&m);
for(int i=;i<=m;++i)scanf("%d",&pos[i]);
ll l=,r=maxroad;
while(l<r)
{
ll mid=(l+r)>>;
if(check(mid))r=mid;//,printf("%lld 1\n",mid);
else l=mid+;//,printf("%lld 0\n",mid);
}
printf("%lld",l);
}
【NOIP2012】疫情传递的更多相关文章
- Luogu 1084 NOIP2012 疫情控制 (二分,贪心,倍增)
Luogu 1084 NOIP2012 疫情控制 (二分,贪心,倍增) Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是 ...
- [NOIP2012]疫情控制 贪心 二分
题面:[NOIP2012]疫情控制 题解: 大体思路很好想,但是有个细节很难想QAQ 首先要求最大时间最小,这种一般都是二分,于是我们二分一个时间,得到一个log. 然后发现一个军队,越往上走肯定可以 ...
- NOIP2012 疫情控制 题解(LuoguP1084)
NOIP2012 疫情控制 题解(LuoguP1084) 不难发现,如果一个点向上移动一定能控制更多的点,所以可以二分时间,判断是否可行. 但根节点不能不能控制,存在以当前时间可以走到根节点的点,可使 ...
- noip2012 疫情控制
[问题描述] H国有n个城市,这n个城市用n-1条双向道路相互连通构成一棵树,1号城市是首都,也是树中的根节点. H国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子 ...
- NOIP2012疫情控制(二分答案+倍增+贪心)
Description H国有n个城市,这n个城市用n-1条双向道路相互连通构成一棵树,1号城市是首都,也是树中的根节点. H国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境 ...
- NOIP2012疫情控制(二分答案+树上贪心)
H 国有n个城市,这 n个城市用n-1条双向道路相互连通构成一棵树,1号城市是首都,也是树中的根节点. H国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示 ...
- [NOIP2012]疫情控制(二分答案+倍增+贪心)
Description H国有n个城市,这n个城市用n-1条双向道路相互连通构成一棵树,1号城市是首都,也是树中的根节点. H国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境 ...
- [NOIp2012]疫情控制 题解
好久没更,强迫自己写一篇. 神 tm 大预言家出的题 注意到如果 \(x\) 小时可以控制住疫情,则 \(\forall x'>x\) 必然也可以控制住疫情,显然答案具有单调性,可以二分答案. ...
- luogu1084 [NOIp2012]疫情控制 (二分答案+倍增+dfs序)
先二分出一个时间,把每个军队倍增往上跳到不能再跳 然后如果它能到1号点,就记下来它跳到1号点后剩余的时间:如果不能,就让它就地扎根,记一记它覆盖了哪些叶节点(我在这里用了dfs序+差分,其实直接dfs ...
随机推荐
- ASP.NET Core WebApi 返回统一格式参数(Json 中 Null 替换为空字符串)
相关博文:ASP.NET Core WebApi 返回统一格式参数 业务场景: 统一返回格式参数中,如果包含 Null 值,调用方会不太好处理,需要替换为空字符串,示例: { "respon ...
- 关于java以及JavaScript或者更多的语言中Data类的问题
关于java和JavaScript以及各类编程语言里Data类的月份问题,日子是从1开始数,但是星期和月份对应的周一和1月都不是1,这是为什么呢? 很多新手对此可能会不理解,老手觉得这没啥,但是我觉得 ...
- sublime text 3配置使用python
1. 在sublime text的官网下载,是适合自己系统的版本.官网地址:https://www.sublimetext.com/3 2. 安装好后,在菜单栏打开:Preferences---> ...
- 数据库、ArcCatalog空间数据源正常访问,数据库设置没问题时,ArcEngine连接SDE时报"ORA-12560: TNS: 协议适配器错误"的解决办法;ArcEngine连接SDE总结
碰到的问题描述: 通过C# 基于ArcEngine写SDE直连的时候测试项目连接属性设置为如下: tPropSet.SetProperty("User", "GISDAT ...
- Springboot-添加对jsp支持
1,在项目的配置文件加入以下依赖 <dependency> <groupId>javax.servlet</groupId> <artifactId>j ...
- JavaScript--AJAX页面传值
1.首先 闲话不说 直接代码走起,都是我工作闲事的积累干货 //重要 js 运行 $(function (){ 代码 }); 2.ajax 传值 //第一种 输入框 <input type=&q ...
- iOS PickerView选择视图
原文demo: @interface ViewController ()<UIPickerViewDelegate,UIPickerViewDataSource> { UIPickerVi ...
- 关于C++函数返回局部对象的详细分析
以前一直挺好奇的,C++是怎么在函数内返回一个局部对象的.因为按照我之前的想法,函数返回一个基本类型的值是通过存放到ecx实现的(关于浮点不了解),但是局部对象又是比较大的,很明显不能使用寄存器作为通 ...
- ToolStrip和MenuStrip控件簡介及常用屬性(转)
ToolStrip和MenuStrip實際上是相同的控件,因為MenuStrip直接派生於ToolStrip.也就是說ToolStrip可以做的工作,MenuStrip也能完成. ToolStrip( ...
- scala写算法-List、Stream、以及剑指Offer里部分题目基于scala解法
Stream(immutable) Stream是惰性列表.实现细节涉及到lazy懒惰求值.传名参数等等技术(具体细节详见维基百科-求值策略). Stream和List是scala中严格求值和非严格求 ...