题解

二分时间

然后一个显然的事是一个军队向上爬的越高它控制的点越多

所以首先军队尽量往上爬。

当一个军队可以爬到根节点我们记录下它的剩余时间T和它到达根结点时经过的根节点的子节点son。

当一个军队爬不到根节点时我们就让它控制它可以爬到的最高点。

然后我们把爬到根节点的军队按T从小到大排序。

然后按顺序处理

然后假如一个军队没有时间回到它的son,且son还没有控制。就让它控制son。

因为让别的军队去控制它显然更浪费时间。

否则贪心地匹配就好了(尽量小的和小的和匹配)

然后向上爬用倍增来优化。

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
priority_queue<long long,vector<long long>,greater<long long> > q1,q2;
const int N=;
int cnt,head[N],fa[N][],s[N][],top[N],book[N],xb[N],ww[N],www[N],n,m;
long long rest[N];
struct edge{
int nxt,to,w;
}e[];
struct node{
int id,xb;
long long rest;
}k[N];
bool cmp(node a,node b){
return a.rest<b.rest;
}
void add(int u,int v,int w){
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
e[cnt].w=w;
head[u]=cnt;
}
void dfs(int u,int f,int fl){
fa[u][]=f;
s[u][]=fl;
for(int i=;i<=;i++){
fa[u][i]=fa[fa[u][i-]][i-];
s[u][i]=s[fa[u][i-]][i-]+s[u][i-];
}
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==f)continue;
dfs(v,u,e[i].w);
}
}
void dfs1(int u,int f,int tp){
top[u]=tp;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==f)continue;
dfs1(v,u,tp);
}
}
void dfs2(int u,int f){
if(book[u]==)return;
book[u]=;
bool flag=false;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==f)continue;
dfs2(v,u);
if(book[v]==)book[u]=;
flag=true;
}
if(!flag)book[u]=;
}
bool pd(long long maxx){
while(!q1.empty())q1.pop();
while(!q2.empty())q2.pop();
for(int i=;i<=n;i++)book[i]=;
for(int i=;i<=m;i++){
k[i].xb=ww[i];
k[i].rest=maxx;
k[i].id=i;
for(int j=;j>=;j--){
if(fa[k[i].xb][j]&&k[i].rest>=s[k[i].xb][j]){
k[i].rest-=s[k[i].xb][j];
k[i].xb=fa[k[i].xb][j];
}
}
}
sort(k+,k++m,cmp);
for(int i=;i<=m;i++){
if(k[i].xb!=)book[k[i].xb]=;
}
dfs2(,);
for(int i=;i<=m;i++){
if(k[i].xb==&&k[i].rest<www[top[ww[k[i].id]]]&&book[top[ww[k[i].id]]]==)book[top[ww[k[i].id]]]=;
else if(k[i].xb==&&(k[i].rest>=www[top[ww[k[i].id]]]||(k[i].rest<www[top[ww[k[i].id]]]&&book[top[ww[k[i].id]]])))q1.push(k[i].rest);
}
if(book[])return true;
for(int i=head[];i;i=e[i].nxt){
if(book[e[i].to]==)q2.push(e[i].w);
}
while(!q2.empty()){
int a=q2.top();
q2.pop();
while(!q1.empty()&&q1.top()<a)q1.pop();
if(q1.empty())return false;
q1.pop();
}
return true;
}
int main(){
scanf("%d",&n);
for(int i=,u,v,w;i<=n-;i++){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
for(int i=head[];i;i=e[i].nxt){
www[e[i].to]=e[i].w;
dfs1(e[i].to,,e[i].to);
}
dfs(,,);
scanf("%d",&m);
for(int i=;i<=m;i++){
scanf("%d",&ww[i]);
}
long long l=,r=,ans;
while(l<=r){
long long mid=(l+r)>>;
if(pd(mid)){
r=mid-;
ans=mid;
}
else l=mid+;
}
if(r==)printf("-1");
else printf("%lld",ans);
return ;
}

NOIP 2012 疫情控制(二分+贪心+倍增)的更多相关文章

  1. 【NOIP 2012 疫情控制】***

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

  2. 基础算法(二分,贪心):NOIP 2012 疫情控制

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

  3. LUOGU P1084 疫情控制(二分+贪心+树上倍增)

    传送门 解题思路 比较神的一道题.首先发现是最小值问题,并且具有单调性,所以要考虑二分答案.其次有一个性质是军队越靠上越优,所以我们要将所有的军队尽量向上提,这一过程我们用倍增实现.发现这时有两种军队 ...

  4. 洛谷P1084 疫情控制(贪心+倍增)

    这个题以前写过一遍,现在再来写,感觉以前感觉特别不好写的细节现在好些多了,还是有进步吧. 这个题的核心思想就是贪心+二分.因为要求最小时间,直接来求问题将会变得十分麻烦,但是如果转换为二分答案来判断可 ...

  5. noip 2012 疫情控制

    /* 考试的时候没想出正解 也没打暴力 时间不够了 随便yy了几种情况按出现的先后顺序处理而没有贪心 的了20分 不粘了 正解是围绕首都的儿子来搞的 显然先二分答案 对于每个限定的最大时间 我们尝试着 ...

  6. luogu1084 [NOIp2012]疫情控制 (二分答案+倍增+dfs序)

    先二分出一个时间,把每个军队倍增往上跳到不能再跳 然后如果它能到1号点,就记下来它跳到1号点后剩余的时间:如果不能,就让它就地扎根,记一记它覆盖了哪些叶节点(我在这里用了dfs序+差分,其实直接dfs ...

  7. 洛谷P1084 疫情控制 [noip2012] 贪心+树论+二分答案 (还有个小bugQAQ

    正解:贪心+倍增+二分答案 解题报告: 正好想做noip的题目然后又想落实学长之前讲的题?于是就找上了这题 其实之前做过,70,然后实在细节太多太复杂就不了了之,现在再看一遍感觉又一脸懵了... 从标 ...

  8. P1080 【NOIP 2012】 国王游戏[贪心+高精度]

    题目来源:洛谷 题目描述 恰逢 H国国庆,国王邀请n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排成一排,国王 ...

  9. 【NOIP 2012 国王游戏】 贪心+高精度

    题目描述 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右 手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排 成一排,国王站在队伍 ...

随机推荐

  1. Android 数据存取

    Android提供了Preference(配置),File(文件),SQLite数据和网络几种数据存取方式 SharedPreference提供了一种轻量级的数据存取方法,应用场合主要是比较少的配置信 ...

  2. C++之易混淆知识点二

    1.数据抽象与封装 数据抽象是一种接口和实现相分离的编程技术,设计者关心的是如何实现这些接口,而使用者仅仅知道这些接口,抽象地考虑这些接口做什么的就可以了,不必去考虑如何实现这一层次. 封装是将低层次 ...

  3. (转载) 据说年薪30万的Android程序员必须知道的

    据说年薪30万的Android程序员必须知道的帖子 标签: android 2015-03-12 16:52 28705人阅读 评论(14) 收藏 举报 Android中国开发精英 目前包括: And ...

  4. 在javascript中对于this指向的再次理解

    总所周知,function () {}函数体内的this对象指向的是调用该函数的对象,那么我们看一下这个例子 <script> var length = 3; function fn () ...

  5. FCC编程题之中级算法篇(上)

    介绍 FCC: 全称为freeCodeCamp,是一个非盈利性的.面向全世界的编程练习网站.这次的算法题来源于FCC的中级算法题. FCC中级算法篇共分为(上).(中).(下)三篇.每篇各介绍7道算法 ...

  6. 安卓、safari和微信各个浏览器的设计标准

  7. (2016北京集训十四)【xsy1556】股神小D - LCT

    题解: 题解居然是LCT……受教了 把所有区间按照端点排序,动态维护目前有重叠的区间,用LCT维护即可. 代码: #include<algorithm> #include<iostr ...

  8. luogu P4430 小猴打架(prufer编码与Cayley定理)

    题意 n个点问有多少种有顺序的连接方法把这些点连成一棵树. (n<=106) 题解 了解有关prufer编码与Cayley定理的知识. 可知带标号的无根树有nn-2种.然后n-1条边有(n-1) ...

  9. CF1005F Berland and the Shortest Paths (树上构造最短路树)

    题目大意:给你一个边权为$1$的无向图,构造出所有$1$为根的最短路树并输出 性质:单源最短路树上每个点到根的路径 ,一定是这个点到根的最短路之一 边权为$1$,$bfs$出单源最短路,然后构建最短路 ...

  10. 洛谷 P2279 [HNOI2003]消防局的设立 (树形dp or 贪心)

    一看到这道题就知道是树形dp 之前做过类似的题,只不过保护的范围是1 所以简单很多. 这道题保护的范围是2,就复杂了很多. 我就开始列状态,然后发现竟然有5种 然后我就开始列方程. 但是我考虑的时候是 ...