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\n",res); 58 } 59 return 0; 60 }