zoukankan      html  css  js  c++  java
  • P2986 [USACO10MAR]Great Cow Gathering G(树形DP)

    题意:

    给出一棵树,

    每个点有点权,每条边有边权。

    定义答案为所有点自身的点权乘上它到根节点的距离之和。

    询问怎么选择根节点使得答案最小。

    题解:

    计算出每个点子树内的所有点权之和。

    计算出每个点子树外的所有点权之和。

    换根的时候,答案加上子树外的所有点权之和乘上这条边的权值,减去子树内的所有点权之和乘上这条边的权值,可以做到(O(1))转移。

    总体时间复杂度(O(n))

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+100;
    int n;
    long long c[maxn];
    long long sz[maxn];
    vector<pair<int,int> > g[maxn];
    long long ans=1e18;
    long long sum=0;
    void dfs (int x,int pre,long long dep) {
    	sz[x]=c[x];
    	sum+=c[x]*dep;
    	for (pair<int,int> y:g[x]) {
    		if (y.first==pre) continue;
    		dfs(y.first,x,dep+y.second);
    		sz[x]+=sz[y.first];
    	}
    }
    void dfs1 (int x,int pre,long long sum) {
    	ans=min(ans,sum);
    	for (pair<int,int> y:g[x]) {
    		if (y.first==pre) continue;
    		dfs1(y.first,x,sum-sz[y.first]*y.second+(sz[1]-sz[y.first])*y.second);
    	}
    }
    int main () {
    	cin>>n;
    	for (int i=1;i<=n;i++) cin>>c[i];
    	for (int i=1;i<n;i++) {
    		int a,b,l;
    		cin>>a>>b>>l;
    		g[a].push_back(make_pair(b,l));
    		g[b].push_back(make_pair(a,l));
    	}
    	dfs(1,0,0);
    	dfs1(1,0,sum);
    	printf("%lld
    ",ans);
    }
  • 相关阅读:
    【洛谷P1119】灾后重建
    【洛谷P1462】通往奥格瑞玛的道路
    【洛谷P1991】无线通讯网
    poj 2892(二分+树状数组)
    hdu 1541(树状数组)
    hdu 5059(模拟)
    hdu 5056(尺取法思路题)
    poj 2100(尺取法)
    hdu 2739(尺取法)
    poj 3320(尺取法)
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/14643658.html
Copyright © 2011-2022 走看看