题解

这题是真的烦。。。

越来越心疼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. python内置函数(四)

    python内部提供了非常多内建函数. 以下让我们从a-z開始学习python的内建函数 1.1 id(object) 返回对象的id(身份),返回的这个是一个整数(integer)是唯一的,在这个对 ...

  2. 深入了解MyBatis返回值

    深入了解MyBatis返回值 想了解返回值,我们须要了解resultType,resultMap以及接口方法中定义的返回值. 我们先看resultType和resultMap resultType和r ...

  3. 沉迷 Docker,无法自拔(在 Docker 中运行 MySQL)

    记得之前做网站开发的时候,因为服务端用的 MySQL 数据库,为了方便调试以及隔离生产与开发环境,自己就在本地也安装了一个 MySQL 数据库.但是用着用着慢慢的也发现了一些不舒服的地方,比如常驻后台 ...

  4. BeautifulSoup 抓取网站url

    1 # -*- coding:utf-8 -*- 2 import urlparse 3 import urllib2 4 from bs4 import BeautifulSoup 5 6 url ...

  5. 管道设计CAD系统中重量重心计算

    管道设计CAD系统中重量重心计算 eryar@163.com Abstract. 管道设计CAD系统中都有涉及到重量重心计算的功能,这个功能得到的重心数据主要用于托盘式造船时方便根据重心设置吊装配件. ...

  6. 小白的Python之路 day2 字符编码和转码

    字符编码和转码 详细文章: http://www.cnblogs.com/yuanchenqi/articles/5956943.html http://www.diveintopython3.net ...

  7. jmeter+ant+jenkins的自动化接口测试

    一.Jenkins安装配置 1.安装配置JDK1.7+环境变量: 2.下载jenkins.war,放入D:\jenkins目录下,目录位置随意: Jenkins启动方法: cmd进入Jenkins目录 ...

  8. iOS自定义文字高度添加行间距

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000 } span.s1 { } span.s2 { c ...

  9. Java I/O---类体系总结

    1.Java I/O常用 (1)File 对文件系统中文件以及文件夹进行封装的对象,可以通过对象的思想来操作文件和文件夹. (2)FileInputStream 从文件系统中的某个文件中获得输入字节: ...

  10. Jenkins 关闭和重启实现方式.

    1.关闭Jenkins 只需要在访问jenkins服务器的网址url地址后加上exit.例如我jenkins的地址http://localhost:8080/,那么我只需要在浏览器地址栏上敲下http ...