79: cf 444E 并查集+思维

$des$

题面

$sol$

把边从小到大排序,枚举每条边作为答案,然后把两个点合并,
判断每条边是否可以作为答案时,
$cnt_i$ 表示节点 $i$ 已经合并的 $x$ 之和
$size_i$ 表示已经合并的节点的个数
$sum = \sum x$
将 $a$ 与外面的点合并时
判断条件 $size_a <= sum - cnt_a$
并查集维护。

$code$

#include <bits/stdc++.h>

using namespace std;

#define Rep(i, a, b) for(int i = a; i <= b; i ++)

#define gc getchar()
inline int read() {
    int x = 0; char c = gc;
    while(c < '0' || c > '9') c = gc;
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
    return x;
}

const int N = 1e5 + 10;

int n, Cnt[N], Size[N], fa[N], Sum;
struct Node {
    int u, v, w;
    bool operator < (Node a) const {
        return this->w < a.w;
    }
} G[N];
bool Ok;

int Get(int x) {
    return fa[x] == x ? x : fa[x] = Get(fa[x]);
}

void Merge(int x, int y) {
    x = Get(x), y = Get(y);
    Size[x] += Size[y];
    Cnt[x] += Cnt[y];
    fa[y] = x;
    if(Size[x] > Sum - Cnt[x]) Ok = 0;
}

int main() {
    n = read();
    Rep(i, 1, n - 1) G[i] = (Node) {
        read(), read(), read()
    };
    sort(G + 1, G + n);
    Rep(i, 1, n) Cnt[i] = read(), Sum += Cnt[i];
    Rep(i, 1, n) fa[i] = i, Size[i] = 1;
    int Answer = 0;
    Ok = 1;
    Rep(i, 1, n - 1) {
        if(Ok) Answer = G[i].w;
        Merge(G[i].u, G[i].v);
    }
    cout << Answer;
    return 0;
} 

 

posted @ 2018-10-29 15:31  xayata  阅读(325)  评论(0编辑  收藏  举报