2019沈阳网赛树形dp

时间:2019-09-16
本文章向大家介绍2019沈阳网赛树形dp,主要包括2019沈阳网赛树形dp使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

https://nanti.jisuanke.com/t/41403

2019沈阳网络赛D题

树形dp。一棵树,求任意两个点的距离之和。u-v和v-u算两次。两点之间的距离分为三类,模3等于0,1,2三类,最后输出这三类的总和。

第一种方法。直接累加。遍历到一个点的时候。先计算答案。答案加上所有已经遍历过得点到他的距离之和。同时该点也要加上这个值,同时要加上数量。每次先搜到底统计往下遍历的值,然后回溯的时候统计

回溯的值。因为每次只计算了之前的点到他的距离之和,所以最后的结果要乘以2,因为u-v与v-u算两次。

每次加的时候先计算当前点前一个点到他的距离,及0+该边的边权。然后在按0,1,2来累加,如果为零表示没有,就不累加。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e4 + 5;
const int mod = 1e9 + 7;
typedef pair<int, ll> pii;
int n;
vector<pii> g[N];
ll ans[4];//结果数组
struct Node {
    ll valup[4];//递归回溯的时候
    ll valdown[4];//递归往下的时候
    ll cntdown[4], cntup[4];//递归往下与回溯的点数量。
} node[N];

void dfs(int u, int f) {
    int len = g[u].size();
    for(int i = 0; i < len; i++) {
        int v = g[u][i].first;
        ll w = g[u][i].second;
        if(v == f) continue;
        node[v].valdown[w%3] = (node[v].valdown[w%3] + w) % mod;
        node[v].cntdown[w%3] = (node[v].cntdown[w%3] + 1) % mod;
        ans[w%3] = (ans[w%3] + w) % mod;
        for(int j = 0; j < 3; j++) {
            ll ww = (node[u].valdown[j] + node[u].valup[j]) % mod;
            ll cnt = (node[u].cntdown[j] + node[u].cntup[j]) % mod;
            if(ww == 0) continue;
            ll mo = (j + w) % 3;
            node[v].valdown[mo] = (node[v].valdown[mo] + ww) % mod;
            node[v].valdown[mo] = (node[v].valdown[mo] + w * cnt) % mod;
            node[v].cntdown[mo] = (node[v].cntdown[mo] + cnt) % mod;
            ans[mo] = (ans[mo] + ww) % mod;
            ans[mo] = (ans[mo] + w * cnt) % mod;
        }
        dfs(v, u);
        node[u].valup[w%3] = (node[u].valup[w%3] + w) % mod;
        node[u].cntup[w%3] = (node[u].cntup[w%3] + 1) % mod;
        for(int j = 0; j < 3; j++) {
            ll ww = node[v].valup[j];
            ll cnt = node[v].cntup[j];
            if(ww == 0) continue;
            ll mo = (j + w) % 3;
            node[u].valup[mo] = (node[u].valup[mo] + ww) % mod;
            node[u].valup[mo] = (node[u].valup[mo] + w * cnt) % mod;
            node[u].cntup[mo] = (node[u].cntup[mo] + cnt) % mod;
        }
    }
}

int main() {
    while(~scanf("%d", &n)) {
        int u, v;
        ll w;
        ans[0] = ans[1] = ans[2] = 0;
        for(int i = 0; i < n; i++) {
            g[i].clear();
            for(int j = 0; j < 4; j++) node[i].valup[j] = node[i].valdown[j] = node[i].cntdown[j] = node[i].cntup[j] = 0;
        }
        for(int i = 1; i < n; i++) {
            scanf("%d%d%lld", &u, &v, &w);
            g[u].push_back(pii(v, w));
            g[v].push_back(pii(u, w));
        }
        dfs(0, -1);
        for(int i = 0; i < 3; i++) {
            printf("%lld%c", (ans[i] * 2) % mod, i == 2 ? '\n' : ' ');
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/downrainsun/p/11528832.html