bzoj 4033
树形DP,dp[i][j]表示i子树中,选了j个白点,i子树中所有边的贡献。
1 /************************************************************** 2 Problem: 4033 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:6568 ms 7 Memory:32492 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #define min(a,b) ((a)<(b)?(a):(b)) 12 #define max(a,b) ((a)>(b)?(a):(b)) 13 #define oo 0x3f3f3f3f3f3f3f3fLL 14 #define N 2010 15 16 typedef long long dnt; 17 18 int n, m; 19 int head[N], next[N+N], dest[N+N], wght[N+N], etot; 20 dnt siz[N]; 21 dnt dp[N][N], pp[N]; 22 23 void adde( int u, int v, int w ) { 24 etot++; 25 wght[etot] = w; 26 dest[etot] = v; 27 next[etot] = head[u]; 28 head[u] = etot; 29 } 30 void dfs( int u, int fa ) { 31 siz[u] = 1; 32 for( int t=head[u]; t; t=next[t] ) { 33 int v=dest[t]; 34 if( v==fa ) continue; 35 dfs( v, u ); 36 siz[u] += siz[v]; 37 } 38 int maxc = min( siz[u], m ); 39 for( int c=0; c<=maxc; c++ ) 40 pp[c] = -oo; 41 pp[0] = 0; 42 for( int t=head[u]; t; t=next[t] ) { 43 int v=dest[t], w=wght[t]; 44 if( v==fa ) continue; 45 for( int c=maxc; c>=0; c-- ) { 46 int msc = min( c, siz[v] ); 47 for( int sc=0; sc<=msc; sc++ ) { 48 dnt tv = pp[c-sc]+dp[v][sc]+((dnt)sc*(m-sc)+(siz[v]-sc)*(n-m-siz[v]+sc))*w; 49 pp[c] = max( pp[c], tv ); 50 } 51 } 52 } 53 dp[u][0] = pp[0]; 54 for( int c=1; c<=maxc; c++ ) 55 dp[u][c] = max( pp[c], pp[c-1] ); 56 } 57 58 int main() { 59 scanf( "%d%d", &n, &m ); 60 if( n-m<m ) m=n-m; 61 for( int i=1,u,v,w; i<n; i++ ) { 62 scanf( "%d%d%d", &u, &v, &w ); 63 adde( u, v, w ); 64 adde( v, u, w ); 65 } 66 dfs(1,1); 67 printf( "%lld\n", dp[1][m] ); 68 } 69