【每日一题】8.Shortest Path (树上DFS)

题目链接:Here

题意总结:给定的是无向图(树),要求把分成 \(n/2\) 对 让权值最小

思路:

看一下范围 在加上是一棵树 所以做法应该是dfs 复杂度为 \(\mathcal{O}(n)\)
直接去考虑贡献
设当前父节点为x 如果x的子树(包括x自己)的大小是个奇数 意味着什么呢
因为要两两配对,那么意味着这奇数个数中,一定有一个数要有外界配对
那么他就一定会经过x到x的父节点的那条边

所以 dfs 计算子树的大小 如果子树大小是个奇数 ,那么对答案有贡献 就要加上父节点往上连接的那一条边

AC 代码:246ms,1964kb

using ll    = long long;
const int N = 1e4 + 10;
ll ans;
vector<ll> cnt(N);
vector<pair<int, ll>> e[N];
void dfs(int u, int fa, ll len) {
    for (auto it : e[u]) {
        int v = it.first;
        if (v == fa) continue;
        dfs(v, u, it.second);
        cnt[u] += cnt[v];
    }
    if (cnt[u] & 1) ans += len;
}
void solve() {
    int n;
    cin >> n;
    ans = 0;
    for (int i = 0; i <= n; ++i) e[i].clear();
    for (int i = 0; i <= n; ++i) cnt[i] = 1;
    for (int i = 1, u, v; i < n; ++i) {
        ll len;
        cin >> u >> v >> len;
        e[u].push_back(make_pair(v, len));
        e[v].push_back(make_pair(u, len));
    }
    dfs(1, 0, 0);
    cout << ans << "\n";
}

另外附上学姐讲解:Here

posted @ 2021-04-15 17:07  RioTian  阅读(53)  评论(1编辑  收藏  举报