您的位置:首页 > 其它

poj 1155(树形dp)

2014-05-02 21:16 190 查看
题意:有一个有线电视网络叶子结点是用户,每个用户有一个愿意支付的金额。然后每条边都有话费。问公司在不亏本的情况下最多能满足多少用户。

思路:dp[v][j] = max(dp[v][j], dp[v][j-k]+dp[x][k]-edge(v, x))

其实就是背包问题,但是一开始TLE了一次,这里要有个优化处理一个节点之前需要初始化一下他最多接着几个用户。这样就AC了。

代码如下:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#define MP(a, b) make_pair(a, b)
#define PB(a) push_back(a)
using namespace std;
const int LEN = 3010;
const int INF = 0x3f3f3f3f;
typedef pair<int, int> pii;
int n, m, dp[LEN][LEN], vex[LEN], num[LEN];
vector<pii> Map[LEN];

void dfs(int v, int fa){
if(v > n-m && v <= n) dp[v][1] = vex[v];
for(int i=0; i<Map[v].size(); i++){
int x = Map[v][i].first;
if(x != fa){
dfs(x, v);
num[v] += num[x];
for(int j=num[v]; j>=0; j--){
for(int k=0; k<=num[x]; k++){
if(j - k >= 0 && dp[x][k] != -INF && dp[v][j-k] != -INF)
dp[v][j] = max(dp[v][j], dp[v][j-k]+dp[x][k]-Map[v][i].second);
}
}
}
}
}

void init(){
for(int i=0; i<LEN; i++)Map[i].clear();
memset(num, 0, sizeof num);
for(int i=0; i<LEN ;i++){
for(int j=0; j<LEN; j++){
dp[i][j] = -INF;
if(j == 0) dp[i][j] = 0;
}
}
}

int main()
{
//   freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);

int a, b, tn;
while(scanf("%d%d", &n, &m)!=EOF){
init();
for(int i=1; i<=n-m; i++){
scanf("%d", &tn);
for(int j=0; j<tn; j++){
scanf("%d%d", &a, &b);
Map[i].PB(MP(a, b));
Map[a].PB(MP(i, b));
}
}
for(int i=n-m+1; i<=n ;i++){
num[i] = 1;
scanf("%d", &vex[i]);
}
dfs(1, -1);
int ans;
for(int i=m; i>=0; i--){
if(dp[1][i] >= 0){
ans = i;
break;
}
}
printf("%d\n", ans);
}
return 0;

}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: