题面

这道题由于问最大值最小,所以很容易想到二分,但怎么验证并且如何实现是这道题的难点;

首先我们考虑,对于一个军队,尽可能的往根节点走(但一定不到)是最优的;

判断一个军队最远走到哪可以树上倍增来实现;

但是,这并没有结束,因为可能这颗子树的军队会去另一个军队;

我们先找出所有以根节点的子节点为根的子树中,是否有到叶子节点的路径还未被驻扎,并记录下还有路径未被驻扎的这些子树的根节点;

若该节点上停留有军队,则剩余时间最小的军队驻扎在该节点一定是最优的。

这样处理过这些节点后,把剩下的节点按照到根节点的距离从小到大排序。

对于现在闲置的军队和需要被驻扎的节点,让剩余时间小的军队优先驻扎在距离根节点近的节点,这样可以保证决策最优

#include <bits/stdc++.h>
using namespace std;
const int MXR=5e4+2;
int n,m,t,tot=0,atot=0,btot=0,ctot=0;
int d[MXR],query[MXR],f[MXR][20];
int ver[2*MXR],edge[2*MXR],MXRext[2*MXR],head[MXR],dist[MXR][20];
pair<long long,int> h[MXR];
void add(int x,int y,int z){
ver[++tot]=y,edge[tot]=z,MXRext[tot]=head[x],head[x]=tot;
}
void bfs()
{
queue<int> q;
q.push(1);
d[1]=1;
while(q.size()){
int x=q.front();q.pop();
for(int i=head[x];i;i=MXRext[i]){
int y=ver[i];
if(d[y]) continue;
d[y]=d[x]+1;
f[y][0]=x,dist[y][0]=edge[i];
for(int j=1;j<=t;j++){
f[y][j]=f[f[y][j-1]][j-1];
dist[y][j]=dist[y][j-1]+dist[f[y][j-1]][j-1];
}
q.push(y);
}
}
}
bool ok,sta[MXR],need[MXR];
long long ans,tim[MXR],ned[MXR];
int dfs(register int x)
{
bool pson=0;
if(sta[x]) return 1;
for(int i=head[x];i;i=MXRext[i]){
int y=ver[i];
if(d[y]<d[x]) continue;
pson=1;
if(!dfs(y)) return 0;
}
if(!pson) return 0;
return 1;
}
template<class nT>
inline void read(nT&x)
{
char c;while(c=getchar(),!isdigit(c));
x=c^48;while(c=getchar(),isdigit(c)) x=x*10+c-48;
}
bool check(long long lim)
{
memset(sta,0,sizeof(sta));
memset(tim,0,sizeof(tim));
memset(ned,0,sizeof(ned));
memset(h,0,sizeof(h));
memset(need,0,sizeof(need));
atot=0,btot=0,ctot=0;
for(int i=1;i<=m;i++){
long long x=query[i],cnt=0;
for(int j=t;j>=0;j--)
if(f[x][j]>1 && cnt+dist[x][j]<=lim){
cnt+=dist[x][j];
x=f[x][j];
}
if(f[x][0]==1 && cnt+dist[x][0]<=lim) h[++ctot]=make_pair(lim-cnt-dist[x][0],x);
else sta[x]=1;
}
for(int i=head[1];i;i=MXRext[i]) if(!dfs(ver[i])) need[ver[i]]=1;
sort(h+1,h+ctot+1);
for(int i=1;i<=ctot;i++){
if(need[h[i].second] && h[i].first<dist[h[i].second][0]) need[h[i].second]=0;
else tim[++atot]=h[i].first;
}
for(int i=head[1];i;i=MXRext[i]) if(need[ver[i]]) ned[++btot]=dist[ver[i]][0];
if(atot<btot) return 0;
sort(tim+1,tim+atot+1),sort(ned+1,ned+btot+1);
int i=1,j=1;
while(i<=btot && j<=atot)
if(tim[j]>=ned[i]){
i++,j++;
}
else j++;
if(i>btot)return 1;
return 0;
}
int main()
{
long long l=0,r=0,mid;
cin>>n;
t=log2(n)+1;
for(int i=1;i<=n-1;i++){
int x,y,z;
read(x); read(y); read(z);
add(x,y,z),add(y,x,z);
r+=z;
}
bfs();
cin>>m;
for(int i=1;i<=m;i++) read(query[i]);
while(l<=r){
mid=(l+r)>>1;
if(check(mid)){
r=mid-1;
ans=mid;
ok=1;
}
else
l=mid+1;
}
if(!ok) cout<<-1;
else cout<<ans;
return 0;
}

NOIP2012 D2T3 疫情控制 题解的更多相关文章

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

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

  2. 【NOIP2012】 疫情控制

    [NOIP2012] 疫情控制 标签: 倍增 贪心 二分答案 NOIP Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树, 1 号城市是首都, 也是 ...

  3. luoguP1084 疫情控制(题解)(搜索+贪心)

    luoguP1084 疫情控制 题目 #include<iostream> #include<cstdlib> #include<cstdio> #include& ...

  4. [NOIp2012]疫情控制 题解

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

  5. noip2012疫情控制 题解

    题目大意 给出一棵n个节点的树,根是1,要在除根节点以外的点建立检查点,使得从每条根到叶子的路径上都至少存在一个检查点.检查点由军队来建立.初始军队的位置是给定的,移动军队走一条边需要花费这条边的权值 ...

  6. [LOJ2607]【NOIP2012】疫情控制

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

  7. 【noip2012】疫情控制

    题意: 给出一颗n个节点有边权的树 和m个军队所在的位置 军队从某节点移动到相邻节点要花费边长度的时间 求最少要多少时间使得根节点(编号为1)到每个叶子的路径上最少有一支军队(根节点不能有军队) 题解 ...

  8. 【NOIP2012】疫情控制(二分,倍增,贪心)

    洛谷上的题目链接,题目不在赘述 题解 既然要时间最短,首先考虑二分. 因此,考虑二分时间,问题转换为如何检查能否到达. 如果一支军队一直向上走,能够到达根节点,那么他可以通过根节点到达其他的节点,因此 ...

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

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

随机推荐

  1. SDOI2015 寻宝游戏 | noi.ac#460 tree

    题目链接:戳我 可以知道,我们相当于是把有宝藏在的地方围了一个圈,求这个圈最小是多大. 显然按照dfs序来遍历是最小的. 那么我们就先来一遍dfs序列,并且预处理出来每个点到根的距离(这样我们就可用\ ...

  2. Java web 公文流转系统 完成结果

    河北金力集团公文流转系统 1.项目需求: 河北金力集团是我省机械加工的龙头企业,主要从事矿山机械制造及各种机械零部件加工.企业有3个厂区,主厂区位于省高新技术开发区,3个分厂分别在保定.邢台和唐山.为 ...

  3. 推荐系统系列(三):FNN理论与实践

    背景 在FM之后出现了很多基于FM的升级改造工作,由于计算复杂度等原因,FM通常只对特征进行二阶交叉.当面对海量高度稀疏的用户行为反馈数据时,二阶交叉往往是不够的,三阶.四阶甚至更高阶的组合交叉能够进 ...

  4. JavaWeb_(Struts2框架)Struts创建Action的三种方式

    此系列博文基于同一个项目已上传至github 传送门 JavaWeb_(Struts2框架)Struts创建Action的三种方式 传送门 JavaWeb_(Struts2框架)struts.xml核 ...

  5. $\LaTeX$数学公式大全10

    $10\ Array\ environment,examples$ $\left( \begin{array}{cc} 2\tau & 7\phi-frac5{12} \\ 3\psi &am ...

  6. Leetcode题目22.括号生成(动态规划-中等)

    题目描述: 给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合. 例如,给出 n = 3,生成结果为: [ "((()))", "( ...

  7. vxworks 开发环境搭建

    育儿 分类: 嵌入式开发 VxWorks操作系统是美国WindRiver公司于1983年设计开发的一种嵌入式实操作系统 windriv vxwork时操作系统(RTOS),它以其良好的可靠性和卓越的实 ...

  8. Docker关键概念阐述

    要了解Docker需要对其体系结构中的几个关键概念有所了解,主要包括image.container.service.swarm.stack等. 在介绍这几个概念时,会使用到一个测试环境,这个测试环境是 ...

  9. Android res之shape

    xml控件配置属性 android:background="@drawable/shape" 标签 corners ----------圆角gradient ----------渐 ...

  10. nuros安全报告

    We believe that great technology should benefit everyone. Self-driving vehicles promise to save live ...