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

然后如果它能到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. lnmp如何实现伪静态,默认目录伪静态

    LNMP一键安装包一直是我小内存VPS的首选安装环境,因为它占用资源少,性能高.最新发布的lnmp0.7还增加了对LNMPA的支持,LNMPA使用Nginx作为前端服务能够更快更及时的静态页面.js. ...

  2. 单片机程序在内存和FLASH中的空间分配

    本文转载于的tietao的博客!!!http://blog.csdn.net/tietao/article/details/8172411 *******防止自己忘记,固备之. 一句话:基于速度问题, ...

  3. C语言学习之结构体

    前言 一直以来,C语言的学习都在入门阶段,只用到数组.函数.循环.选择.位运算这些基本的知识,较少用到指针.预处理.结构体.枚举类型.文件操作等这些C语言的精髓内容,现在想想真不敢说自己熟练掌握C语言 ...

  4. SSIS 组件属性整理

    整理SSIS 组件的属性解释及其用法 一,ExecValueVariable属性 有些Task组件执行完成之后,会产生输出结果,称作Execution Value,例如,Execute SQL Tas ...

  5. NodeJs学习一NodeJs初识

    一.前言 按照惯例,先扯淡,就因为这货,现在才有了各大公司招聘的全栈工程师,正是因为它,让以前只会写前端的人也能写起后端服务器代码来了.所以呢,你招一个会NodeJs的前端,它都能把后端干了,一个人干 ...

  6. storm从入门到放弃(三),放弃使用 StreamId 特性

    序:StreamId是storm中实现DAG有向无环图的重要一个特性,但是从实际生产环境来看,这个功能其实蛮影响生产环境的稳定性的,我们系统在迭代时会带来整体服务的不可用. StreamId是stor ...

  7. 微软职位内部推荐-SW Engineer II for Azure Network

    微软近期Open的职位: Software Engineer II The world is moving to cloud computing. Microsoft is betting Windo ...

  8. #个人博客作业Week1——浏览教材后提出的5个问题

    1.对于MSF的团队模型,请问是团队中的哪个角色监督9项原则的实现?是否会浪费时间和精力在践行9项原则上?2.在调查用户需求和用户体验时如何让不同阶层的用户更多的参与度?3.想成为一位优秀的PM需要从 ...

  9. 读书笔记(chapter1-2)

    一.linux内核简介 1.1unix的历史 1.unix强大的根本原因:1.unix很简洁,仅仅提供几百个系统调用并且有一个非常明确的设计目的:2.在unix中,所有的东西都被当作文件对待:3.un ...

  10. 5月29,48h,Geekathon,创业极客的梦想起点

    http://mp.weixin.qq.com/s?__biz=MjM5ODQ3MDIwMg==&mid=213768178&idx=1&sn=0a607fac483f3eab ...