Nuclear Power Plant ZOJ - 3840 树形dp

Posted zxyqzy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nuclear Power Plant ZOJ - 3840 树形dp相关的知识,希望对你有一定的参考价值。

There are N (1 ≤ N ≤ 105) cities on land, and there are N - 1 wires connecting the cities. Therefore, each city can transmit electricity to all other cities by these wires.

Dark_Sun made a decision to build a nuclear power plant to supply electricity for all the cities. The nuclear power plant can be built in any city, but the cost for the electricity transmission is very strange. Let the weight of wire which connects city u and city v is E(u, v) (|E(u, v)| < 109). If the power plant is built in city x, the cost for electricity transmission from city x to city y is D(x, y) = (E(x, s1) + E(s1, s2) + ... + E(sp, y))k, where {x, s1, s2, ..., sp, y} is the path from x to y. Because of the bug of the computer, the total cost for building a nuclear power plant in city x is Σ(D(x, i)) mod 100000007 (0 ≤ i < N, ix), and the total cost is obviously not a negative number.

Dark_Sun asks you to write a program to calculate the minimum total cost.


Input

Input will consist of multiple test cases.

The first line of each test case contains two integers N, K (1 ≤ N ≤ 105,0 ≤ K ≤ 10).

The next N - 1 lines, each line contains three integers u, v, w (0 ≤ u, v < N, |w| < 109, uv), indicating E(u, v) is w.

Output

For each case, output one line with one integer, indicating the minimum total cost.

Sample Input
3 2
0 1 2
1 2 2
Sample Output
8
技术图片
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<time.h>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
//#include<cctype>
//#pragma GCC optimize(2)
using namespace std;
#define maxn 100005
#define inf 0x7fffffff
//#define INF 1e18
#define rdint(x) scanf("%d",&x)
#define rdllt(x) scanf("%lld",&x)
#define rdult(x) scanf("%lu",&x)
#define rdlf(x) scanf("%lf",&x)
#define rdstr(x) scanf("%s",x)
#define mclr(x,a) memset((x),a,sizeof(x))
typedef long long  ll;
typedef unsigned long long ull;
typedef unsigned int U;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 100000007;
#define Mod 1000000000
#define sq(x) (x)*(x)
#define eps 1e-5
typedef pair<int, int> pii;
#define pi acos(-1.0)
//const int N = 1005;
#define REP(i,n) for(int i=0;i<(n);i++)
typedef pair<int, int> pii;

inline int rd() {
	int x = 0;
	char c = getchar();
	bool f = false;
	while (!isdigit(c)) {
		if (c == ‘-‘) f = true;
		c = getchar();
	}
	while (isdigit(c)) {
		x = (x << 1) + (x << 3) + (c ^ 48);
		c = getchar();
	}
	return f ? -x : x;
}


ll gcd(ll a, ll b) {
	return b == 0 ? a : gcd(b, a%b);
}
int sqr(int x) { return x * x; }



/*ll ans;
ll exgcd(ll a, ll b, ll &x, ll &y) {
	if (!b) {
		x = 1; y = 0; return a;
	}
	ans = exgcd(b, a%b, x, y);
	ll t = x; x = y; y = t - a / b * y;
	return ans;
}
*/
int n, K;
struct node {
	int u, v;
	ll w;
	int nxt;
}e[maxn<<1];

ll dp[maxn][12];
int head[maxn];
int tot;
ll C[14][14];

void init() {
	C[0][0] = C[1][1] = C[1][0] = 1;
	for (int i = 2; i <= 13; i++) {
		C[i][i] = C[i][0] = 1;
		for (int j = 1; j < i; j++) {
			C[i][j] = C[i - 1][j - 1] + C[i - 1][j];
			C[i][j] %= mod;
		}
	}
}

void addedge(int u, int v, ll w) {
	e[++tot].u = u; e[tot].v = v; e[tot].w = w; e[tot].nxt = head[u]; head[u] = tot;
}

void dfs1(int u, int fa) {
//	ms(dp[u]);
	dp[u][0] = 1;
	for (int i = head[u]; i; i = e[i].nxt) {
		int v = e[i].v;
		if (v == fa)continue;
		dfs1(v, u);
		for (int k = 0; k <= K; k++) {
			ll ut = 1;
			for (int j = 0; j <= k; j++) {
				dp[u][k] = (dp[u][k] + C[k][j] * dp[v][k - j] % mod*ut%mod) % mod;
				dp[u][k] = (dp[u][k] % mod + mod) % mod;
				ut = ut * e[i].w%mod;
			}
		}
	}
	return;
}

void dfs2(int u, int fa) {
	for (int i = head[u]; i; i = e[i].nxt) {
		int v = e[i].v;
		if (v == fa)continue;
		ll tmp[20];
		for (int k = 0; k <= K; k++) {
			tmp[k] = dp[u][k];
			ll ut = 1;
			for (int j = 0; j <= k; j++) {
				tmp[k] = (tmp[k] - C[k][j] * dp[v][k - j] % mod*ut%mod) % mod;
				tmp[k] = (tmp[k] % mod + mod) % mod;
				ut = ut * e[i].w%mod;
			}
		}
		for (int k = 0; k <= K; k++) {
			ll ut = 1;
			for (int j = 0; j <= k; j++) {
				dp[v][k] = (dp[v][k] + C[k][j] * tmp[k - j] % mod*ut%mod) % mod;
				dp[v][k] = (dp[v][k] % mod + mod) % mod;
				ut = ut * e[i].w%mod;
			}
		}
	}
	for (int i = head[u]; i; i = e[i].nxt) {
		int v = e[i].v;
		if (v == fa)continue;
		dfs2(v, u);
	}
}


int main()
{
//	ios::sync_with_stdio(0);
	init();
	while (scanf("%d%d",&n,&K)!=EOF) {
	//	ms(e);
		ms(head); tot = 0;
    	ms(dp);
		
		for (int i = 1; i < n; i++) {
			int u, v; rdint(u); rdint(v);
			ll w; rdllt(w); u++; v++;
			addedge(u, v, w); addedge(v, u, w);
		}
		if (K == 0) {
			cout << n - 1 << endl;
			continue;
		}
		dfs1(1, -1); dfs2(1, -1);
		ll ans = -inf;
		for (int i = 1; i <= n; i++) {
			if (ans == -inf || ans > dp[i][K])ans = dp[i][K];
		}
		printf("%lld
", 1ll * ans);
	}
	return 0;
}

 




以上是关于Nuclear Power Plant ZOJ - 3840 树形dp的主要内容,如果未能解决你的问题,请参考以下文章

缩点:Power Plant;

LA 6437 Power Plant (prim最小生成树)

Codeforces Round #248 (Div. 1) D - Nanami's Power Plant 最小割

ZOJ1905Power Strings (KMP||后缀数组+RMQ求循环节)

Android开发中如何可以捕获到短按power键的事件

Nuclear Reactor