poj1155 poj2468 树形DP专题。(一)

2014-11-24 10:42:27 · 作者: · 浏览: 0

【序言】树形DP一直不太会。趁着练DP的时候,写了两道树形的背包。鉴于这块知识非常不熟练,网上参考了一点题解。为了加强记忆,特写此题解。

【题目1】

TELE
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 3445 Accepted: 1781

Description

A TV-network plans to broadcast an important football match. Their network of transmitters and users can be represented as a tree. The root of the tree is a transmitter that emits the football match, the leaves of the tree are the potential users and other vertices in the tree are relays (transmitters).
The price of transmission of a signal from one transmitter to another or to the user is given. A price of the entire broadcast is the sum of prices of all individual signal transmissions.
Every user is ready to pay a certain amount of money to watch the match and the TV-network then decides whether or not to provide the user with the signal.
Write a program that will find the maximal number of users able to watch the match so that the TV-network's doesn't lose money from broadcasting the match.

Input

The first line of the input file contains two integers N and M, 2 <= N <= 3000, 1 <= M <= N-1, the number of vertices in the tree and the number of potential users.
The root of the tree is marked with the number 1, while other transmitters are numbered 2 to N-M and potential users are numbered N-M+1 to N.
The following N-M lines contain data about the transmitters in the following form:
K A1 C1 A2 C2 ... AK CK
Means that a transmitter transmits the signal to K transmitters or users, every one of them described by the pair of numbers A and C, the transmitter or user's number and the cost of transmitting the signal to them.
The last line contains the data about users, containing M integers representing respectively the price every one of them is willing to pay to watch the match.

Output

The first and the only line of the output file should contain the maximal number of users described in the above text.

Sample Input

9 6
3 2 2 3 2 9 3
2 4 2 5 2
3 6 2 7 2 8 2
4 3 3 3 1 1

Sample Output

5

Source

Croatia OI 2002 Final Exam - Second Day

【大意】一棵树中有N个节点,编号是最后M个的节点是叶节点。每条边会有一个花费。你从1号点(根节点)开始,如果到达某个叶节点,你就能获得它的权值,但要付出所经过的边的花费。在你获得的利润S>=0的情况下,要求所到达的叶节点尽量的多。

【分析】用f[i][j]表示到i节点,以i为根的子树中到达j个的最大利润。输出时倒着循环枚举,如果f[1][ans]大于等于0就可行。下面研究状态转移方程。以前我一直以为这种选择最优解的题目要把多叉树转化为二叉树,后来发现其实并不用。我们依次枚举每一个孩子。f[k][now]=max(f[k][now],f[k][now-cut]+f[go][cut]-a[i].s);其中now是枚举当前我所在的根的状态,而cut则是给某个孩子的j值。而a[i].s就是边权。

【注意】①点多,建议开边表。

②运算时可能会有负数,一开始初始化时要赋成负无穷大。

【代码】

#include
  
   
#include
   
     using namespace std; const int maxn=3500+5; const int INF=2100000000; struct arr{int r,s,next;}a[maxn]; int num[maxn],ok[maxn],begin[maxn],end[maxn],f[maxn][maxn]; int n,m,x,b,c,i,j,ans,cnt; void make_up(int u,int v,int s) { a[++cnt].r=v;a[cnt].s=s; if (begin[u]==0) {begin[u]=cnt;end[u]=cnt;} else {a[end[u]].next=cnt;end[u]=cnt;} } void dp(int k) { if (k>=n-m+1) { f[k][1]=num[k];ok[k]=1; return; } int i=begin[k]; while (i) { int go=a[i].r; dp(go); ok[k]+=ok[go]; for (int now=ok[k];now>0;now--) for (int cut=0;cut<=ok[go];cut++) f[k][now]=max(f[k][now],f[k][now-cut]+f[go][cut]-a[i].s); i=a[i].next; } } int main() { scanf("%ld%ld",&n,&m); for (i=1;i<=n;i++) for (j=1;j<=m;j++) f[i][j]=-INF; for (i=1;i<=n-m;i++) { scanf("%ld",&x); while (x) { scanf("%ld%ld",&b,&c); make_up(i,b,c);x--; } } for (i=n-m+1;i<=n;i++) scanf("%ld",&num[i]); dp(1); for (ans=m;ans>=0;ans--) if (f[1][ans]>=0) {printf("%ld",ans);break;} return 0; }
   
  


【题目2】

Apple Tree
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 6762 Accepted: 2242

Description

Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to an apple tree. There are N nodes in the tree. Each node has an amount of apples. Wshxzt starts her happy trip at one node. She can eat up all the apples in the nodes she reaches. HX is a kind guy. He knows that eating too many can make the lovely girl become fat. So he doesn’t allow Wshxzt to go more than K steps in the tree. It costs on