http://codevs.cn/problem/1218/

比较显然的倍增,但是对于跨过根需要很多讨论,总体思路是贪心。

写了一上午,不想再说什么了

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 100003;
int in() {
int k = 0, fh = 1; char c = getchar();
for(; c < '0' || c > '9'; c = getchar())
if (c == '-') fh = -1;
for(; c >= '0' && c <= '9'; c = getchar())
k = (k << 3) + (k << 1) + c - '0';
return k * fh;
} struct node {int nxt, to, w;} E[N << 1];
struct data {
ll left; int from;
bool operator < (const data &A) const {
return left < A.left;
}
} A[N], B[N];
struct data2 {
int id, dis;
bool operator < (const data2 &A) const {
return dis < A.dis;
}
} P[N];
int f[N][18], n, m, cnt = 0, point[N], L[N], R[N], w[N], Army[N], a[N], nxt[N], upto[N];
ll c[N][18];
bool mark[N]; void ins(int u, int v, int w) {E[++cnt] = (node) {point[u], v, w}; point[u] = cnt;} void dfs(int x) {
L[x] = ++cnt;
w[cnt] = x;
for(int i = point[x]; i; i = E[i].nxt)
if (E[i].to != f[x][0]) {
f[E[i].to][0] = x;
c[E[i].to][0] = E[i].w;
dfs(E[i].to);
}
R[x] = cnt;
} void pushup_mark(int x) {
if (mark[x]) return;
bool flag = false, marknow = true;
for(int i = point[x]; i; i = E[i].nxt)
if (E[i].to != f[x][0]) {
pushup_mark(E[i].to);
flag = true;
marknow &= mark[E[i].to];
}
if (flag) mark[x] = marknow;
} bool cmp_forMrazer(data X, data Y) {
return X.from == Y.from ? X.left < Y.left : X.from < Y.from;
} bool can(ll up) {
int tmp, tot = 0, tot2 = 0, tot3 = 0; ll ret;
memset(mark, 0, sizeof(bool) * (n + 1));
for(int i = 1; i <= m; ++i) {
ret = up; tmp = Army[i];
for(int j = 17; j >= 0; --j)
if (f[tmp][j] && f[tmp][j] != 1 && c[tmp][j] <= ret) {
ret -= c[tmp][j];
tmp = f[tmp][j];
}
if (c[tmp][0] <= ret) A[++tot] = (data) {ret - c[tmp][0], tmp};
else mark[tmp] = true;
} // for(int i = 1; i <= tot; ++i) printf("left = %I64d from = %d\n", A[i].left, A[i].from); for(int i = point[1]; i; i = E[i].nxt)
pushup_mark(E[i].to); stable_sort(A + 1, A + tot + 1, cmp_forMrazer); for(int i = 1; i <= tot; ++i)
if (!mark[A[i].from])
if (A[i].left <= c[A[i].from][0])
mark[A[i].from] = true;
else
B[++tot3] = A[i];
else
B[++tot3] = A[i];
// printf("%d\n", tot3);
// for(int i = 1; i <= tot3; ++i) printf("left = %I64d from = %d\n", B[i].left, B[i].from); for(int i = point[1]; i; i = E[i].nxt)
if (!mark[E[i].to])
P[++tot2] = (data2) {E[i].to, c[E[i].to][0]}; stable_sort(B + 1, B + tot3 + 1);
stable_sort(P + 1, P + tot2 + 1); // printf("%d %d\n", tot3, tot2); if (tot3 < tot2) return false;
for(; tot3 && tot2; --tot3, --tot2)
if (B[tot3].left < P[tot2].dis) return false;
return true;
} int main() {
n = in();
int u, v, w;
for(int i = 1; i < n; ++i) {
u = in(); v = in(); w = in();
ins(u, v, w);
ins(v, u, w);
} dfs(1);
for(int j = 1; j <= 17; ++j)
for(int i = 1; i <= n; ++i) {
f[i][j] = f[f[i][j - 1]][j - 1];
if (f[i][j]) c[i][j] = c[i][j - 1] + c[f[i][j - 1]][j - 1];
}
m = in();
for(int i = 1; i <= m; ++i) Army[i] = in();
ll left = 0, right = 50000000000000ll, mid;
while (left < right) {
mid = (left + right) >> 1; //printf("left = %I64d mid = %I64d right = %I64d\n", left, mid, right);
if (can(mid)) right = mid;
else left = mid + 1;
} printf("%lld\n", left);
return 0;
}

_(:з」∠)_

【CodeVS 1218】【NOIP 2012】疫情控制的更多相关文章

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

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

  2. NOIP 2012 疫情控制(二分+贪心+倍增)

    题解 二分时间 然后一个显然的事是一个军队向上爬的越高它控制的点越多 所以首先军队尽量往上爬. 当一个军队可以爬到根节点我们记录下它的剩余时间T和它到达根结点时经过的根节点的子节点son. 当一个军队 ...

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

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

  4. noip 2012 疫情控制

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

  5. 【NOIP】提高组2012 疫情控制

    [题意]n个点的树,1为根,要求删除一些点使得截断根节点和所有叶子结点的路径(不能删根,可以删叶子).有m支军队在m个点上,每时刻所有军队可以走一步,最终走到的地方就是删除的点,求最短时间. [算法] ...

  6. Codevs 1218 疫情控制 2012年NOIP全国联赛提高组

    1218 疫情控制 2012年NOIP全国联赛提高组 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description H 国有 n 个城市,这 ...

  7. 疫情控制 2012年NOIP全国联赛提高组(二分答案+贪心)

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

  8. [NOIP2012] 提高组 洛谷P1084 疫情控制

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

  9. [NOIP2012] day2 T3疫情控制

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

  10. 洛谷P1084 [NOIP2012提高组Day2T3]疫情控制

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

随机推荐

  1. Appium学习实践(二)Python简单脚本以及元素的属性设置

    1.简单的Python脚本 Appium中的设置与Appium学习实践(一)简易运行Appium中的一致 Launch后,执行脚本 #coding:utf-8 import unittest impo ...

  2. Unity打包同一文件Hash不一样

    问题起因 游戏开发基本都会涉及到资源版本管理及更新,本文记录我在打包过程中遇到的一小问题: 开过中常用于标记资源版本的方法有计算文件Hash.VCS的版本等. 在Unity中对同一个资源文件进行多次打 ...

  3. 使用mx:Repeater在删除和添加item时列表闪烁

    使用mx:Repeater在删除和添加item时列表闪烁 不可能在用户界面上闪闪的吧,recycleChildren属性可帮助我们 recycleChildren属性==缓存,设为true就可以了 本 ...

  4. 在VMware Workstation上安装CentOS6.5系统步

    在VMware Workstation上安装CentOS6.5系统步骤 听语音 | 浏览:147 | 更新:2016-07-28 15:45 | 标签:安装 虚拟机 CENTOS 1 2 3 4 5 ...

  5. Sublime3安装过程及常用插件安装及常用快捷键

    1  先去http://www.sublimetext.com/官网下载软件,然后网上找一个验证码,注册完成. 2  安装Package Control ,Package Control 插件是一个方 ...

  6. SVN的使用方法

    SVN的使用方法: 新建文件夹:文件夹1 在文件夹上点击右键--选择 SVN Checkout--弹出checkout窗口 下载文件的url获取:打开SVN--在要下载的文件上点击右键--点击Copy ...

  7. Oracle job procedure 存储过程定时任务

    Oracle job procedure 存储过程定时任务 oracle job有定时执行的功能,可以在指定的时间点或每天的某个时间点自行执行任务. 一.查询系统中的job,可以查询视图 --相关视图 ...

  8. CSS3之文本阴影text-shadow

  9. 包含文件函数include与require的区别

    include或include_once一般用于动态包含,所谓动态包含就是根据不同条件包含不同文件 require或require_once一般用于静态包含,比如包含一个html文件的头部或者尾部 如 ...

  10. vuejs全局api

    全局api set 增加数组 vm.$set 实例化方法 全局api delete 删除数组 vm.$delete 实例化方法 全局 api 组件component 实例化方法 components ...