【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 ...
随机推荐
- 機器學習基石 (Machine Learning Foundations) 作业1 Q15-17的C++实现
大家好,我是Mac Jiang.今天和大家分享Coursera-台湾大学-機器學習基石 (Machine Learning Foundations) -作业1的Q15-17题的C++实现. 这部分作业 ...
- HDOJ--4893--Wow! Such Sequence!【线段树+单点、区间更新】
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4893 题意:给你一个长度n的数列,初始都为0.有三种操作,第一种给第k个位置的数加d.另外一种是查询区间 ...
- ASP.NET Core 返回 Json DateTime 格式
ASP.NET Core 返回 Json 格式的时候,如果返回数据中有DateTime类型,如何自定义其格式呢?配置如下: services.AddMvc().AddJsonOptions(opt = ...
- Python的类(class)
python 3.6 官方文档 https://docs.python.org/3.6/index.html python 3.6 的类 https://docs.python.org/3.6/tu ...
- Caused by: com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'name': was expecting ('true', 'false' or 'null')
Caused by: com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'name': was expecting ( ...
- 【java设计模式】【创建模式Creational Pattern】单例模式Singleton Pattern
//饿汉式:资源利用率较低(无论是否需要都会创建),性能较高(使用前无需判断实例是否存在,可直接使用) public class EagerSingleton{ private static fina ...
- 串String(2):串的实现(堆分配存储表示法)
7/27/2017,先占个位,最近事情比较忙,明天敲一波代码,预测在一星期内搞定 9/02/2017,看到这个十分汗颜,八月去美帝学习了,没有抽空补上这一博文,计划这个月开了数据结构课后补上
- 关于llvm kaleidoscope: 记一次Debug血泪之路
简而言之,慎(bu)用(yong)全局变量! 这次debug基本上花了我一周的时间,我基本上是晚上9点30下自习回然后调试到11点30,如此反复一周直到今天周五终于解决了,,以前都听说前辈们 说尽量不 ...
- git pull与git fetch的区别
git pull: 取回远程主机某个分支的更新,再与本地的指定分支合并. 用法: git pull <远程仓库> <远程分支名>:<本地分支名> // 如 git ...
- c#全宇宙最牛的编程软件
c#走的道路!PC,PD,电脑一体,一个账户就可以三合一,可以跨平台的编程,在未来的道路如果微软能一直走下去,那么c#将成为宇宙最牛B的编程软件.