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

然后如果它能到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. 2018-3-7 20155317 王新玮 Exp1 PC平台逆向破解(5)M

    2018-3-7  20155317  王新玮 Exp1 PC平台逆向破解(5)M 任务要求:手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数. NOP.JNE.JE.JMP.CM ...

  2. 【MEF】构建一个WPF版的ERP系统

    原文:[MEF]构建一个WPF版的ERP系统 引言 MEF是微软的一个扩展性框架,遵循某种约定将各个部件组合起来.而ERP系统的一大特点是模块化,它们两者的相性很好,用MEF构建一个ERP系统是相当合 ...

  3. debian系统下改语言设置

    debian系统下改语言设置 安装debian 的时候选择了中文zh_CN_UTF-8,然后进系统后想换成en_US_UTF-8 可以使用一下命令选择:找到需要的语言 确定即可 dpkg-reconf ...

  4. 微信小程序 Echarts 异步数据更新

    微信小程序 Echarts 异步数据更新的练习,被坑了很多次,特作记录. 作者:罗兵 地址:https://www.cnblogs.com/hhh5460/p/9989805.html 0.效果图   ...

  5. PHP7添加opcache.so模块

    启动php报错如下: # /usr/local/php7/sbin/php-fpm [-Apr- ::] NOTICE: PHP message: PHP Warning: PHP Startup: ...

  6. Django的跨域请求

    一 同源策略 同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响.可以说Web是构建在同源策略基础之 ...

  7. 从字节码层面,解析 Java 布尔型的实现原理

    最近在系统回顾学习 Java 虚拟机方面的知识,其中想到一个很有意思的问题:布尔型在虚拟机中到底是什么类型? 要想解答这个问题,我们看 JDK 的源码是无法解决源码的,我们必须深入到 class 文件 ...

  8. redis见解

    http://blog.csdn.net/zhiguozhu/article/details/50517527Redis原生session与redis中的session区别原生session在服务器上 ...

  9. Sleeping会话导致阻塞原理(上)

    背景 我在处理客户问题的时候,客户经常搞不懂sleeping 的由来,和他可能导致的问题.下面来详细说下 什么是sleeping 其实我们经常可以在数据库中看到“”sleeping“状态的连接,但是这 ...

  10. 谷歌商店高级搜索 Google play advanced search

    这个问题一直搜索了很久都没有答案,后来在StackOverflow上提问,很久也没人回答. 详见我的SO:https://stackoverflow.com/questions/52939493/ho ...