zoukankan      html  css  js  c++  java
  • P2986 [USACO10MAR]伟大的奶牛聚集

    题意:

    给一棵 n 个点的边 + 点权树,求带权重⼼ 
     

    思路:

    其实这题和之前那个 Sta 有点像,我们同样只需要预处理出一个 f[u] 代表以 u 为集合点的方便程度,那么我们就可以O(1)的转移了

    假设 v 是 u 的儿子,f[v] = f[u] - (siz[v] * len) + (n - siz[v] ) * len = f[u] + (n - 2 * siz[v] )  * len

    这题有一个坑,就是你的INF得开的特别大,不然你就没有 100 了

    #include <iostream>
    #include <algorithm>
    #include <string>
    #include <string.h>
    #include <vector>
    #include <map>
    #include <stack>
    #include <set>
    #include <queue>
    #include <math.h>
    #include <cstdio>
    #include <iomanip>
    #include <time.h>
    #include <bitset>
    #include <cmath>
    
    #define LL long long
    #define INF 0x3f3f3f3f3f3f3f3f
    #define ls nod<<1
    #define rs (nod<<1)+1
    
    const double eps = 1e-10;
    const int maxn = 1e5 + 10;
    const LL mod = 1e9 + 7;
    
    int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;}
    using namespace std;
    
    struct edge {
        int v,nxt,w;
    }e[maxn << 1];
    
    int head[maxn];
    LL siz[maxn],dis[maxn],num[maxn],f[maxn];
    int cnt,n;
    LL ans;
    
    inline void add_edge(int u,int v,int w) {
        e[++cnt].v = v;
        e[cnt].w = w;
        e[cnt].nxt = head[u];
        head[u] = cnt;
    }
    
    inline void dfs(int u,int f) {
        siz[u] = num[u];
        for (int i = head[u];~i;i = e[i].nxt) {
            int v = e[i].v,len = e[i].w;
            if (v == f)
                continue;
            dis[v] = dis[u] + len;
            dfs(v,u);
            siz[u] += siz[v];
        }
    }
    
    inline void func(int x,int fa) {
        for (int i = head[x];~i;i = e[i].nxt) {
            int v = e[i].v,len = e[i].w;
            if (v == fa)
                continue;
            f[v] = f[x] - siz[v] * len + (siz[1] - siz[v]) * len;
            func(v,x);
        }
    }
    
    int main() {
        memset(head,-1, sizeof(head));
        cnt = 0;
        ans = INF;
        cin >> n;
        for (int i = 1;i <= n;i++) {
            cin >> num[i];
        }
        for (int i = 1;i < n;i++) {
            int u,v,w;
            cin >> u >> v >> w;
            add_edge(u,v,w);
            add_edge(v,u,w);
        }
        dfs(1,0);
        for (int i = 1;i <= n;i++) {
            f[1] += (dis[i]*num[i]);
        }
        func(1,0);
        for (int i = 1;i <= n;i++) {
            ans = min(ans,f[i]);
        }
        cout << ans << endl;
        return 0;
    }
  • 相关阅读:
    【思维导图】前端开发JavaScript-巩固你的JavaScript知识体系
    前端面试日更解答 2020-03-28
    CSS基础知识
    HTML基础知识
    Web页面制作基础
    前端面试日更解答 2020-03-24
    前端面试日更解答 2020-03-23
    前端面试日更解答 2020-03-22
    前端面试日更解答 2020-03-21
    前端面试日更解答 2020-03-20
  • 原文地址:https://www.cnblogs.com/-Ackerman/p/12339717.html
Copyright © 2011-2022 走看看