POJ1155 TELE(树形DP)
生活随笔
收集整理的這篇文章主要介紹了
POJ1155 TELE(树形DP)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目是說給一棵樹,葉子結點有負權,邊有正權,問最多能選多少個葉子結點,使從葉子到根的權值和小于等于0。
考慮數據規模表示出狀態:dp[u][k]表示在u結點為根的子樹中選擇k個葉子結點的最小權值
最后就從d[1][k]中找滿足的最大的k。不過單這樣轉移時間復雜度是指數級,顯然這題就是用樹上背包了。
不過其實這題時間復雜度不會算= =反正感覺挺靠譜,交了就AC了。。
又做了一道樹上背包,HDU1561和POJ3345。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 #define INF (1<<29) 6 #define MAXN 3001 7 struct Edge{ 8 int u,v,w,next; 9 }edge[MAXN]; 10 int NE,head[MAXN]; 11 void addEdge(int u,int v,int w){ 12 edge[NE].u=u; edge[NE].v=v; edge[NE].w=w; 13 edge[NE].next=head[u]; head[u]=NE++; 14 } 15 16 int d[MAXN][MAXN],size[MAXN]; 17 void dfs(int u){ 18 bool isleaf=1; 19 for(int i=head[u]; i!=-1; i=edge[i].next){ 20 int v=edge[i].v; 21 dfs(v); 22 size[u]+=size[v]; 23 isleaf=0; 24 } 25 if(isleaf) size[u]=1; 26 } 27 int val[MAXN]; 28 void dp(int u){ 29 bool isleaf=1; 30 for(int i=head[u]; i!=-1; i=edge[i].next){ 31 int v=edge[i].v; 32 dp(v); 33 isleaf=0; 34 for(int j=size[u]; j>=1; --j){ 35 for(int k=1; k<=min(j,size[v]); ++k) d[u][j]=min(d[u][j],d[u][j-k]+d[v][k]+edge[i].w); 36 } 37 } 38 if(isleaf) d[u][1]=-val[u]; 39 } 40 int main(){ 41 memset(head,-1,sizeof(head)); 42 int n,m,k,a,b; 43 scanf("%d%d",&n,&m); 44 for(int i=1; i<=n; ++i){ 45 for(int j=1; j<=m; ++j) d[i][j]=INF; 46 } 47 for(int i=1; i<=n-m; ++i){ 48 scanf("%d",&k); 49 while(k--){ 50 scanf("%d%d",&a,&b); 51 addEdge(i,a,b); 52 } 53 } 54 for(int i=n-m+1; i<=n; ++i){ 55 scanf("%d",val+i); 56 } 57 dfs(1); 58 dp(1); 59 for(int i=m; i>=0; --i){ 60 if(d[1][i]<=0){ 61 printf("%d",i); 62 break; 63 } 64 } 65 return 0; 66 }?
轉載于:https://www.cnblogs.com/WABoss/p/5270220.html
總結
以上是生活随笔為你收集整理的POJ1155 TELE(树形DP)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 拦截器 过滤器 监听器 的区别
- 下一篇: 极限与连续知识点总结_高数上知识点期末复