20200403 Shortest Path

下载pdf,获得更好的阅读体验。

提取码:f1ji

题意翻译

有一棵有 个结点的树( 为偶数)将其划分为 对点对,使得点对间距离综合最小,求该最小值。

多测, 组测试数据。


题解

为了值最小,显然尽量不选重的。

对于一棵子树,如果它的大小是偶数,则可以在这个子树内完成配对。

如果它是奇数,则有一个点要继续向上配对。无论是和根结点还是和其他子树,这个点额外的贡献都是父节点往这个子树的连边。

只要 dfs 一遍就可以得出答案。


Code

#include<bits/stdc++.h>
using namespace std;

typedef long long LL;

const int maxn = 10000 + 7;
const int maxm = 20000 + 7;

int T;
int n, Head[maxn], to[maxm], Next[maxm], w[maxm], tot;

void addedge(int x, int y, int z) {
    to[++tot] = y, Next[tot] = Head[x], Head[x] = tot, w[tot] = z;
}
void add(int x, int y, int z) {
    addedge(x, y, z); addedge(y, x, z);
}

void clear(void) {
    tot = 0;
    memset(Head, 0, sizeof(Head));
    memset(Next, 0, sizeof(Next));
}

void Init(void) {
    scanf("%d", &n);
    for(int i = 1, x, y, z; i < n; i++) {
        scanf("%d%d%d", &x, &y, &z);
        add(x, y, z);
    }
}

LL ans;

int dfs(int x, int f, LL l) {
    int size = 1;
    for(int i = Head[x]; i; i = Next[i]) {
        int y = to[i];
        if(y == f) continue;
        size += dfs(y, x, (LL)w[i]);
    }
    if(size & 1) ans += l;
    return size;
}

void Work(void) {
    ans = 0;
    dfs(1, 0, 0);
    printf("%lld\n", ans);
}

int main(void) {
    scanf("%d", &T);
    while(T--) {
        clear();
        Init();
        Work();
    }
}