【CodeVS 1218】【NOIP 2012】疫情控制

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#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;
}

_(:з」∠)_

posted @   abclzr  阅读(335)  评论(0编辑  收藏  举报
编辑推荐:
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· .NET 进程 stackoverflow异常后,还可以接收 TCP 连接请求吗?
阅读排行:
· 本地部署 DeepSeek:小白也能轻松搞定!
· 基于DeepSeek R1 满血版大模型的个人知识库,回答都源自对你专属文件的深度学习。
· 在缓慢中沉淀,在挑战中重生!2024个人总结!
· Tinyfox 简易教程-1:Hello World!
· 大人,时代变了! 赶快把自有业务的本地AI“模型”训练起来!
点击右上角即可分享
微信分享提示