• UPC12798 FZB


    题目链接

    题目描述

    Hja有一棵N个点的树,树上每个点有点权,每条边有颜色。
    一条路径的权值是这条路径上所有点的点权和,一条合法的路径需要满足该路径上任意相邻的两条边颜色都不相同。
    问这棵树上所有合法路径的权值和是多少。

    输入

    第一行一个数N。
    接下来一行N个数代表每个点的权值。
    接下来N−1行每行三个整数s,e,c,代表s到e之间有一条颜色为c的边。

    输出

    一行一个整数代表答案。

    样例输入

    6
    6 2 3 7 1 4
    1 2 1
    1 3 2
    1 4 3
    2 5 1
    2 6 2
    

    样例输出

    134
    

    提示

    对于30%的数据,1≤N≤1000。
    对于另外20%的数据,数据随机。
    对于另外20%的数据,是一条链。
    对于100%的数据,(1≤N≤3×10^5,1≤c≤10^9)

    树形dp,(val[i])表示以i为路径一个端点,其子树中一点为另一点时的权值和,cnt[i]表示以i为路径一个端点,其子树中一点为另一点时的方案数。

    答案的计算:

    • i为路径端点
      • i为一个端点,其子树中一点为另一个端点
      • i出现在其它点的子树中,作为端点
    • i为路径上的点
      • 两个端点在其子树中
      • 一个端点在子树中,另一个在i的祖先中
    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef unsigned long long ull;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    const int maxn = 2e6 + 100;
    
    struct Edge {
        int to, next, col;
    } e[maxn];
    int head[maxn];
    int tot;
    ll a[maxn], ans, val[maxn], cnt[maxn];
    
    void addedge(int u, int v, int col) {
        tot++;
        e[tot].to = v, e[tot].col = col, e[tot].next = head[u], head[u] = tot;
    }
    
    void dfs(int now, int pre, int pcol) {
        for (int i = head[now]; i; i = e[i].next) {
            if (e[i].to == pre) continue;
            dfs(e[i].to, now, e[i].col);
            if (e[i].col != pcol) {
                cnt[now] += cnt[e[i].to];
                val[now] += cnt[e[i].to] * a[now] + val[e[i].to];
            }
            ans += cnt[e[i].to] * a[now] + val[e[i].to];//以now为一端,子树中一点为另一端时的贡献
        }
        cnt[now] += 1, val[now] += a[now];
        for (int i = head[now]; i; i = e[i].next) {
            if (e[i].to == pre) continue;
            for (int j = i; j; j = e[j].next) {
                if (e[j].to == pre)continue;
                if (e[i].col != e[j].col) {
                    ans += cnt[e[i].to] * val[e[j].to] + cnt[e[j].to] * val[e[i].to] + a[now] * cnt[e[i].to] * cnt[e[j].to];//两个端点在now的子树中
                }
            }
        }
    
    }
    
    
    int main() {
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
    #endif
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%lld", &a[i]);
        }
        int u, v, w;
        for (int i = 1; i < n; i++) {
            scanf("%d %d %d", &u, &v, &w);
            addedge(u, v, w);
            addedge(v, u, w);
        }
        dfs(1, 0, 0);
        printf("%lld
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    windows服务安装命令
    vue开发
    Quorum(NRW)算法机制简介
    SideCar模式
    Python抓取数据的几种方式
    Ms SqlServer索引的选择
    cmd添加环境变量
    好用工具网站
    Aufofac生命周期
    EF初次加载优化
  • 原文地址:https://www.cnblogs.com/albert-biu/p/12673183.html
Copyright © 2020-2023  润新知