HDU3586 Information Disturbing(树形DP)

题目大概说一棵树有边权,要删掉一些边,使叶子到达不了树根1且删掉边的权和小于等于m,问删掉边中最大权的最小值能是多少。

考虑问题规模,与转移的时间复杂度,用这么个状态dp:

  • dp[u][k]表示在u结点为根的子树中,使其叶子到达不了根的,删掉边的最大权小于等于k的最小被删边权和

转移略蛋疼,初始值的设之类的感觉有点不统一。。反正最后感觉自己写得有点挫。。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 #pragma comment(linker,"/STACK:102400000,102400000")
 6 #define INF 1100000
 7 #define MAXN 1111
 8 struct Edge{
 9     int v,w,next;
10 }edge[MAXN<<1];
11 int NE,head[MAXN];
12 void addEdge(int u,int v,int w){
13     edge[NE].v=v; edge[NE].w=w; edge[NE].next=head[u];
14     head[u]=NE++;
15 }
16 long long d[MAXN][1001];
17 int mx;
18 void dp(int u,int w){
19     if(u!=1){
20         for(int i=w; i<=mx; ++i) d[u][i]=w;
21     }
22     long long tmp[1001]={0};
23     for(int i=head[u]; i!=-1; i=edge[i].next){
24         int v=edge[i].v;
25         dp(v,edge[i].w);
26         for(int j=1; j<=mx; ++j){
27             tmp[j]+=d[v][j];
28         }
29     }
30     for(int i=1; i<=mx; ++i){
31         if(tmp[i]==0) continue;
32         d[u][i]=min(d[u][i],tmp[i]);
33     }
34 }
35 int main(){
36     int n,m,a,b,c;
37     while(~scanf("%d%d",&n,&m) && (n||m)){
38         NE=0;
39         memset(head,-1,sizeof(head));
40         mx=0;
41         for(int i=1; i<n; ++i){
42             scanf("%d%d%d",&a,&b,&c);
43             addEdge(a,b,c);
44             mx=max(mx,c);
45         }
46         for(int i=1; i<=n; ++i){
47             for(int j=1; j<=mx; ++j) d[i][j]=INF;
48         }
49         dp(1,0);
50         int res=-1;
51         for(int i=1; i<=mx; ++i){
52             if(d[1][i]<=m){
53                 res=i;
54                 break;
55             }
56         }
57         printf("%d
",res);
58     }
59     return 0;
60 }
原文地址:https://www.cnblogs.com/WABoss/p/5316980.html