NOIP2012 疫情控制 题解(LuoguP1084)

不难发现,如果一个点向上移动一定能控制更多的点,所以可以二分时间,判断是否可行。

但根节点不能不能控制,存在以当前时间可以走到根节点的点,可使向下走到深度为2的节点控制

其他点,此时又可以进行另一个贪心,优先选择走到根节点还能再走的时间小的去控制深度一到二之间边权较小的。

某大佬有更加详尽的讲解,参见这里

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; typedef long long ll;
const int MAXN=50000+5;
int anc[21][MAXN];
ll tab[21][MAXN];
struct Edge
{
int t,v,n;
}e[MAXN<<1];
int cnt,n,m,scnt;
int rsn[MAXN],siz[MAXN],army[MAXN],hd[MAXN],frm[MAXN];
bool cvef[MAXN],cover[MAXN];
typedef pair<int,int> pii;
pii a[MAXN],c[MAXN]; inline void build(int f,int t,int v)
{
e[++cnt]=(Edge){t,v,hd[f]};
hd[f]=cnt;
} void dfs1(int u)
{
if(anc[0][u]==1)
frm[u]=u;
else frm[u]=frm[anc[0][u]];
for(int i=hd[u];i;i=e[i].n)
{
int v=e[i].t;
if(v==anc[0][u])
continue;
++siz[u];
anc[0][v]=u;
tab[0][v]=e[i].v;
for(int i=1;anc[i-1][v];++i)
{
anc[i][v]=anc[i-1][anc[i-1][v]];
tab[i][v]=tab[i-1][v]+tab[i-1][anc[i-1][v]];
}
dfs1(v);
}
} void dfs2(int u)
{
cvef[u]=1;
if(siz[u]>1)
return;
for(int i=hd[u];i;i=e[i].n)
if(e[i].t!=anc[0][u])
dfs2(e[i].t);
}
void initrt()
{
for(int i=hd[1];i;i=e[i].n)
{
int v=e[i].t;
rsn[++scnt]=v;
dfs2(v);
}
} bool check(ll mid)
{
memset(cover,0,sizeof cover);
int cntc=0,cnta=0;
for(int i=1;i<=m;++i)
{
ll tmp=mid;
int pos=army[i];
for(int j=20;j>=0;--j)
{
if(anc[j][pos]&&tmp>=tab[j][pos])
{
tmp-=tab[j][pos];
pos=anc[j][pos];
}
}
if(pos!=1)
{
if(cvef[pos])
cover[frm[pos]]=1;
}
else
a[++cnta]=pii(tmp,frm[army[i]]);
}
for(int i=1;i<=scnt;++i)
{
if(!cover[rsn[i]])
c[++cntc]=pii(tab[0][rsn[i]],rsn[i]);
}
if(cntc>cnta)
return 0;
sort(a+1,a+cnta+1);
sort(c+1,c+cntc+1);
int j=1;
int t=cntc;
for(int i=1;i<=cnta;++i)
{
if(!cover[a[i].second])
cover[a[i].second]=1,--t;
else
{
while(j<=cntc&&cover[c[j].second])
++j;
if(a[i].first>=c[j].first)
cover[c[j].second]=1,++j,--t;
}
}
if(t>0)
return 0;
return 1;
} int main()
{
scanf("%d",&n);
int x,y,z;
ll l=0,r=0;
for(int i=1;i<n;++i)
{
scanf("%d%d%d",&x,&y,&z);
build(x,y,z);
build(y,x,z);
r+=z;
}
scanf("%d",&m);
for(int i=1;i<=m;++i)
scanf("%d",&army[i]);
dfs1(1);
initrt();
if(m<scnt)
{
puts("-1");
return 0;
}
while(r-l>1)
{
ll mid=l+r>>1;
if(check(mid))
r=mid;
else
l=mid;
}
printf("%lld",r);
return 0;
}

看来是只是贪心二分等基础算法我也不会QAQ

NOIP2012 疫情控制 题解(LuoguP1084)的更多相关文章

  1. noip2012疫情控制 题解

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

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

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

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

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

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

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

  5. NOIP2012 D2T3 疫情控制 题解

    题面 这道题由于问最大值最小,所以很容易想到二分,但怎么验证并且如何实现是这道题的难点: 首先我们考虑,对于一个军队,尽可能的往根节点走(但一定不到)是最优的: 判断一个军队最远走到哪可以树上倍增来实 ...

  6. noip2012 疫情控制

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

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

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

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

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

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

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

随机推荐

  1. Bestcoder Round #84

    A题 Aaronson http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=718&pid=1001 感觉一 ...

  2. TCP和UDP Socket

    1.tcp协议的编程 * 1:客户端.步骤  *         1:创建Socket对象,构造方法里需要指定服务端的ip地址和端口.  *         Socket socket = new S ...

  3. Octopus系列之更新历史记录

    更新笔记历史 2015.2.3 更新了产品价格的计算方法     --采用了通用化的一个处理[支持各个国家货币]更新产品价格,增加两组价格:一组用来进行前台的展示:一组用来进行后台的计算更新了产品分类 ...

  4. UTF-8 GB2321

    已知:汉字“你”UTF8编码是 0xe4bda0,GBK编码是 0xc4e3,求证. 0xe4bda0 → 2进制11100100 10111101 10100000 → UTF8 3字节111001 ...

  5. Bitset位图

    位图(bitmap)就是用每一位来存放某种状态,适合于大规模数据但是数据状态又不是很多的情况下,通常来判断数据是否存在.位图的常见应用有两种: 1.存放大规模数据,例如腾讯的面试题,给40亿个unsi ...

  6. dom4j基本使用用法

        DOM4J是dom4j.org出品的一个开源XML解析包,它的网站中这样定义: Dom4j is an easy to use, open source library for working ...

  7. Adaline网络识别印刷体数字0到9-java实现

    本篇只给出实现的代码,下一篇将讲一讲实现的原理,及其Adline网络中的LMS算法原理. 包含两个类: package com.cgjr.com; import java.security.Diges ...

  8. MAVEN_day02快速入门

    一.MAVEN工程目录结构 二.怎么在Eclipse中集成M2E插件(工欲善其事必先利其器)有一些准备工作 1.修改自己下载的MAVEN 2.设置本地仓库 三.构建MAVEN工程 1.选择“MAVEN ...

  9. Python基础二字符串和变量

    了解一下Python中的字符串和变量,和Java,c还是有点区别的,别的不多说,上今天学习的代码 Python中没有自增自减这一项,在转义字符那一块,\n,\r\n都是表示回车,但是对于不同的操作系统 ...

  10. 喵哈哈村的魔法考试 Round #9 (Div.2) 题解

    A题 喵哈哈村的数据筛选游戏 题解:这道题签到题,拿个数组记录一下这个数是否出现过即可. #include<bits/stdc++.h> using namespace std; cons ...