题解

这题是真的烦。。。

越来越心疼2012年的dalao们了【不过好像dalao们都不需要本蒟蒻的心疼2333】

其实这题还有点半懂不懂。。。

所以把洛谷上一个比较好的题解粘过来记忆一下233

1.预处理倍增

我们会发现,离根节点越近的节点,控制的节点更多。所以由贪心的思想,所有的军队都要尽可能地往根节点走。

> ”往上提“类型问题一般使用倍增优化。——xzy神犇

xzy神犇的博客:k-xzy.cf

好大的,那么我们可以dfs一遍,将倍增要用的一些值都处理好(见代码)

2.二分答案

军队可以同时移动,说明我们要控制传染病的时间是军队移动到位时,移动时间最长的军队的移动时间。而我们要求最小值,即要求最大化最小值。

> 二分答案一般用于求最大化最小值,最小化最大值。——jyf神犇

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】疫情传递的更多相关文章

  1. Luogu 1084 NOIP2012 疫情控制 (二分,贪心,倍增)

    Luogu 1084 NOIP2012 疫情控制 (二分,贪心,倍增) Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是 ...

  2. [NOIP2012]疫情控制 贪心 二分

    题面:[NOIP2012]疫情控制 题解: 大体思路很好想,但是有个细节很难想QAQ 首先要求最大时间最小,这种一般都是二分,于是我们二分一个时间,得到一个log. 然后发现一个军队,越往上走肯定可以 ...

  3. NOIP2012 疫情控制 题解(LuoguP1084)

    NOIP2012 疫情控制 题解(LuoguP1084) 不难发现,如果一个点向上移动一定能控制更多的点,所以可以二分时间,判断是否可行. 但根节点不能不能控制,存在以当前时间可以走到根节点的点,可使 ...

  4. noip2012 疫情控制

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

  5. NOIP2012疫情控制(二分答案+倍增+贪心)

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

  6. NOIP2012疫情控制(二分答案+树上贪心)

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

  7. [NOIP2012]疫情控制(二分答案+倍增+贪心)

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

  8. [NOIp2012]疫情控制 题解

    好久没更,强迫自己写一篇. 神 tm 大预言家出的题 注意到如果 \(x\) 小时可以控制住疫情,则 \(\forall x'>x\) 必然也可以控制住疫情,显然答案具有单调性,可以二分答案. ...

  9. luogu1084 [NOIp2012]疫情控制 (二分答案+倍增+dfs序)

    先二分出一个时间,把每个军队倍增往上跳到不能再跳 然后如果它能到1号点,就记下来它跳到1号点后剩余的时间:如果不能,就让它就地扎根,记一记它覆盖了哪些叶节点(我在这里用了dfs序+差分,其实直接dfs ...

随机推荐

  1. 浅析node.js

    大家好,今天来给大家讨论node.js这个东西,说起这个东西啊,可能大家已经很熟悉了,因为现在市场上运用的越来越广泛,毕竟它的优点还是有目共睹的! 那么,什么是node.js呢?官方给出了这样的定义: ...

  2. maven安装配置及使用maven创建一个web项目

    今天开始学习使用maven,现在把学习过程中的资料整理在这边. 第一部分.maven安装和配置. http://jingyan.baidu.com/article/295430f136e8e00c7e ...

  3. 控制反转-Ioc之Unity

    本篇幅主要介绍控制反转的一些概念,和如何使用Unity实现Ioc.在介绍的时候,会尽量结合代码来讲解一些概念. 1.什么是DI? DI即控制反转,是将对具体实现类的依赖转变为对接口的依赖,这样在编程中 ...

  4. org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation

    异常信息 org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable represen ...

  5. git入门(msysgit安装)

    1.下载git-for-windows 常用的GitHub客户端msysgit,也就是git-for-windows. 登录官网 https://git-for-windows.github.io/, ...

  6. 函数PYXX_READ_PAYROLL_RESULT的dump问题

    发现有两个HR的后台定时任务出现dump,日志表示,是PYXX_READ_PAYROLL_RESULT产生了类型冲突的异常CX_SY_DYN_CALL_ILLEGAL_TYPE. 日志标题部分: 类别 ...

  7. 个人的MySql配置总结

    lower_case_table_names参数是用来设置MySQL是否让Schema和数据表大小写敏感,我测试的是在查询界面和MySQL控制台界面无法改变它的值,要在配置文件中改变(先关闭服务),一 ...

  8. Akka Serialization

    Akka本身使用了Protocol Buffers来序列化内部消息(比如gossip message).Akka系统还可以配置自定义序列化机制. 配置conf akka { actor { ## 在a ...

  9. UVALive 4850 Installations

    题目大意:有若干个任务,每个任务耗时si,期限为di,同一时间只能做一个任务.对于一个任务,惩罚值为max(0,完成时间-期限).问怎么安排,使(最大惩罚值+次大惩罚值)最小,O(n^2). 如果没有 ...

  10. linux下制作镜像文件

    第一:制作iso镜像的方法: 把/dev/cdrom目录制作为镜像,名字为/root/rh1.iso 方法1:dd if=/dev/cdrom of=/root/rh1.iso 方法2:#cat /d ...