先二分出一个时间,把每个军队倍增往上跳到不能再跳

然后如果它能到1号点,就记下来它跳到1号点后剩余的时间;如果不能,就让它就地扎根,记一记它覆盖了哪些叶节点(我在这里用了dfs序+差分,其实直接dfs就行..)

然后对于那些叶节点没有被覆盖完全的(父亲为1号点的)子树,肯定需要一些已经到1号点的军队来走过去

如果它离1距离越远,肯定就希望用剩余时间越多的军队来走,除非是有一个剩余时间更少的军队本来就在这个子树里

看一看能不能符合要求的就行了

然而有很多要注意的地方:

0.一个军队只能用一次......(开始读错题 还在想为什么会有-1的情况)

1.只需要覆盖叶节点就行了,也就是说,统计这个子树有没有完全被覆盖的时候,不能统计到非叶节点

2.即使有军队本来在这个子树里,我也有可能不选这个军队来到这个子树里,因为它的剩余时间可能非常大

3.有可能到1号点的军队数不足覆盖掉那些没被覆盖的子树,这时候也是-1

4.每次judge要清零...

 #include<bits/stdc++.h>
#define pa pair<int,int>
#define CLR(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=5e4+; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} struct Edge{
int b,ne;ll l;
}eg[maxn*];
int egh[maxn],ect;
int N,M,p[maxn];
int dfn[maxn][],tot,fa[maxn][];
int bel[maxn],cnt[maxn],tmp[maxn],tmp2[maxn];
int mim[maxn],id[maxn];
bool flag[maxn],islef[maxn];
ll dis[maxn][],rest[maxn]; inline void adeg(int a,int b,ll l){
eg[++ect].b=b;eg[ect].l=l;eg[ect].ne=egh[a];egh[a]=ect;
} void dfs(int x){
dfn[x][]=++tot;id[tot]=x;
for(int i=;fa[x][i]&&fa[fa[x][i]][i];i++){
fa[x][i+]=fa[fa[x][i]][i];
dis[x][i+]=dis[x][i]+dis[fa[x][i]][i];
}islef[x]=;
for(int i=egh[x];i;i=eg[i].ne){
int b=eg[i].b;
if(b==fa[x][]) continue;
fa[b][]=x;dis[b][]=eg[i].l;
if(x==) bel[b]=b;
else bel[b]=bel[x];
dfs(b);
islef[x]=;
}
dfn[x][]=tot;
} int getfe(int x,ll &lim){
for(int i=;i>=;i--){
if(fa[x][i]&&dis[x][i]<=lim) lim-=dis[x][i],x=fa[x][i];
}
return x;
} inline bool cmp(int a,int b){return rest[a]>rest[b];}
inline bool cmp2(int a,int b){return dis[a][]>dis[b][];} inline bool judge(ll m){
// printf("!!%lld:\n",m);
int n,i,j;
CLR(cnt,);
for(i=,j=;i<=M;i++){
rest[i]=m;
int x=getfe(p[i],rest[i]);
// printf("%d %d %lld\n",p[i],x,rest[i]);
if(x==) tmp[++j]=i;
else{
cnt[dfn[x][]]++;
cnt[dfn[x][]+]--;
}
}
n=j;sort(tmp+,tmp+n+,cmp);
CLR(flag,);
for(i=,j=;i<=N;i++){
j+=cnt[i];
if(j==&&islef[id[i]]) flag[bel[id[i]]]=;
}
CLR(mim,);
for(i=n;i;i--){
if((!flag[bel[p[tmp[i]]]])&&(!mim[bel[p[tmp[i]]]])){
mim[bel[p[tmp[i]]]]=i;
}
}
for(i=,j=;i<=N;i++){
if(fa[i][]!=||flag[i]) continue;
tmp2[++j]=i;
}m=j;
sort(tmp2+,tmp2+m+,cmp2);
if(n<m) return ;
for(i=,j=;i<=n&&j<=m;i++){
if(!tmp[i]) continue;
if(tmp[mim[tmp2[j]]]){
tmp[mim[tmp2[j]]]=;
i--;
}else{
if(rest[tmp[i]]<dis[tmp2[j]][]) return ;
tmp[i]=;
}j++;
}
return j>m;
} int main(){
// freopen("testdata (1).in","r",stdin);
int i,j,k;
N=rd();
for(i=;i<N;i++){
int a=rd(),b=rd(),c=rd();
adeg(a,b,c);adeg(b,a,c);
}dfs();
M=rd();
for(i=;i<=M;i++) p[i]=rd();
ll l=,r=1e15,ans=1e15+;
while(l<=r){
ll m=l+r>>;
if(judge(m)) ans=m,r=m-;
else l=m+;
}
if(ans==1e15+) printf("-1\n");
else printf("%lld\n",ans);
return ;
}

luogu1084 [NOIp2012]疫情控制 (二分答案+倍增+dfs序)的更多相关文章

  1. Luogu1084 NOIP2012D2T3 疫情控制 二分答案、搜索、贪心、倍增

    题目传送门 题意太长就不给了 发现答案具有单调性(额外的时间不会对答案造成影响),故考虑二分答案. 贪心地想,在二分了一个时间之后,军队尽量往上走更好.所以我们预处理倍增数组,在二分时间之后通过倍增看 ...

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

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

  3. Luogu P1084 疫情控制 | 二分答案 贪心

    题目链接 观察题目,答案明显具有单调性. 因为如果用$x$小时能够控制疫情,那么用$(x+1)$小时也一定能控制疫情. 由此想到二分答案,将问题转换为判断用$x$小时是否能控制疫情. 对于那些在$x$ ...

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

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

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

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

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

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

  7. 【bzoj3779】重组病毒 LCT+树上倍增+DFS序+树状数组区间修改区间查询

    题目描述 给出一棵n个节点的树,每一个节点开始有一个互不相同的颜色,初始根节点为1. 定义一次感染为:将指定的一个节点到根的链上的所有节点染成一种新的颜色,代价为这条链上不同颜色的数目. 现有m次操作 ...

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

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

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

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

随机推荐

  1. map的综合例子

    #include<iostream> #include<string> #include<map> #include<fstream> #include ...

  2. 大数据入门第十九天——推荐系统与mahout(一)入门与概述

    一.推荐系统概述 为了解决信息过载和用户无明确需求的问题,找到用户感兴趣的物品,才有了个性化推荐系统.其实,解决信息过载的问题,代表性的解决方案是分类目录和搜索引擎,如hao123,电商首页的分类目录 ...

  3. go语言之行--golang核武器goroutine调度原理、channel详解

    一.goroutine简介 goroutine是go语言中最为NB的设计,也是其魅力所在,goroutine的本质是协程,是实现并行计算的核心.goroutine使用方式非常的简单,只需使用go关键字 ...

  4. python 回溯法 子集树模板 系列 —— 14、最长公共子序列(LCS)

    问题 输入 第1行:字符串A 第2行:字符串B (A,B的长度 <= 1000) 输出 输出最长的子序列,如果有多个,随意输出1个. 输入示例 belong cnblogs 输出示例 blog ...

  5. FIFO IP核

    转载: 说白了,IP核就是别人做好了的硬件模块,提供完整的用户接口和说明文档,更复杂的还有示例工程,你只要能用好这个IP核,设计已经完成一半了.说起来容易,从冗长的英文文档和网上各个非标准教程中汲取所 ...

  6. 解决 div 设为 inline-block 后标题不对齐

    vertical-align 属性设置元素的垂直对齐方式.该属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐.允许指定负长度值和百分比值.这会使元素降低而不是升高.在表单元格中,这个属性会设置 ...

  7. KNN算法的R语言实现

    近邻分类 简言之,就是将未标记的案例归类为与它们最近相似的.带有标记的案例所在的类. 应用领域: 1.计算机视觉:包含字符和面部识别等 2.推荐系统:推荐受众喜欢电影.美食和娱乐等 3.基因工程:识别 ...

  8. c语言连接mysql数据库的实现方法

    C语言连接mysql数据库,需要相应的头文件和lib文件,如果你安装Mysql数据库,会在安装目录下找到这些库文件,如果没有安装,也可以在网上找到 我这里也有一份网上找到的:/201205/other ...

  9. 解决SSH登录用户执行的命令部分环境变量参数不生效的问题

    问题概况 linux机器在/etc/profile配置完成环境变量后,SSH到目标机器执行命令,但是获取不到已配置的环境变量值. 例如场景: 在/etc/profile配置了http代理 export ...

  10. MySQL——约束(constraint)详解

    该博客说说关于数据库中一个重要的知识点——约束 一.什么是约束约束英文:constraint 约束实际上就是表中数据的限制条件 二.约束作用表在设计的时候加入约束的目的就是为了保证表中的记录完整和有效 ...