hdu 3586 树形DP+二分法

来源:互联网 发布:2015淘宝交易额 编辑:程序博客网 时间:2024/05/29 17:50

这题要求limit的值,但是因为limit的值是在1到1000之间,可以用二分法来枚举。找出最小的即可。

dp[i]表示切断i的所以子孙叶子的最小总和。

然后递推关系就是如下:

if( edge[i].length <= limit ){
   sum += min( edge[i].length, dp[t] );
 }else{
   sum += dp[t];
 }

dp[i] = sum;

注意,叶子节点应该是无穷大。而这个无穷大的设置既不能大也不能下!

AC代码如下:

#include <iostream>#include <cstring>#include <cstdio>using namespace std;typedef struct{int to;int next;int length;}Edge;Edge edge[2002];int head[1001];int tot;int limit, up, low;int dp[1001];int MAXN = 1000010;int N, M;inline int max( int a, int b ){return ( a > b ? a : b );}inline int min( int a, int b ){return ( a < b ? a : b );}void add_edge( int a, int b, int length ){edge[tot].to = b;edge[tot].length = length;edge[tot].next = head[a];head[a] = tot++;edge[tot].to = a;edge[tot].length = length;edge[tot].next = head[b];head[b] = tot++;}void DFS( int n, int pre ){if( head[n] == -1 || edge[head[n]].to == pre && edge[head[n]].next == -1 ){dp[n] = MAXN;return;}int sum = 0;for( int i = head[n]; i != -1; i = edge[i].next ){int t = edge[i].to;if( t == pre ){continue;}DFS( t, n );if( edge[i].length <= limit ){sum += min( edge[i].length, dp[t] );}else{sum += dp[t];}}dp[n] = sum;}int main(){while( cin >> N >> M && !( N == 0 && M == 0 ) ){tot = 0;memset( head, -1, sizeof( head ) );up = 0;low = 1001;for( int i = 1; i < N; i++ ){int temp1, temp2, temp3;cin >> temp1 >> temp2 >> temp3;add_edge( temp1, temp2, temp3 );up = max( up, temp3 );low = min( low, temp3 );}int ans = MAXN;while( low <= up ){limit = ( low + up ) / 2;DFS( 1, 0 );if( dp[1] <= M ){ans = min( ans, limit );up = limit - 1;}else{low = limit + 1;}}if( ans < MAXN ){cout << ans << endl;}else{cout << -1 << endl;}}return 0;}


 

原创粉丝点击