http://acm.hust.edu.cn/vjudge/problem/16417
重做了一遍poj 1155
题目大意:给定一棵树,1为根结点表示电视台,有m个叶子节点表示客户,有n-m-1个中间节点表示中转站,每条树边有权值。现在要在电视台播放一场比赛,每个客户愿意花费cost[i]的钱观看,而从电视台到每个客户也都有个费用,并且经过一条边只会产生一个费用。问电视台不亏损的情况最多有几个客户可以看到比赛?1<=n<=1000,1<=m<=n-1;
树形背包问题,对于一个树的dp,可以从子节点入手,分析子节点和根节点关系,得到状态转移方程
之前做的:http://www.cnblogs.com/qlky/p/5650783.html
重做的时候遇到了一点问题,居然出现了Output Limit Exceeded。原因在这一行:
while(~sf("%d%d",&n,&m),m+n)
我沿用上一道题的表达式,这样写在这题是错的,正确的写法是
while(~sf("%d%d",&n,&m))
或者
while(~sf("%d%d",&n,&m) && n+m)
按照题意,n>=2,m>=1,第一个逗号表达式的值是m+n的值,可能是负数,0或正数。
while只有在条件等于0时会结束,也就是m+n等于0时结束,题目并没有这么要求,所以不能在这里这么用
贴一下完整代码:
#include <iostream> #include <string> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <algorithm> #include <stack> #include <queue> #include <cctype> #include <vector> #include <iterator> #include <set> #include <map> #include <sstream> using namespace std; #define mem(a,b) memset(a,b,sizeof(a)) #define pf printf #define sf scanf #define spf sprintf #define pb push_back #define debug printf("! ") #define MAXN 3000+5 #define MAX(a,b) a>b?a:b #define blank pf(" ") #define LL long long #define ALL(x) x.begin(),x.end() #define INS(x) inserter(x,x.begin()) #define pqueue priority_queue #define INF 0x3f3f3f3f #define ls (rt<<1) #define rs (rt<<1|1) int n,m; int head[MAXN],vis[MAXN],ptr=1; int num[MAXN],dp[MAXN][MAXN],tmp[MAXN]; struct node{int y,next,val;}tree[MAXN<<2]; void init() { mem(head,-1); mem(vis,0); ptr = 1; } void add(int son,int fa,int val) { tree[ptr].y=son; tree[ptr].val=val; tree[ptr].next=head[fa]; head[fa]=ptr++; } void dfs(int rt) { vis[rt] = 1; for(int i=head[rt];i!=-1;i=tree[i].next) { int y = tree[i].y; if(vis[y]) continue; dfs(y); for(int j=0;j<=num[rt];j++) tmp[j] = dp[rt][j]; for(int j=0;j<=num[rt];j++) { for(int k=1;k<=num[y];k++) { dp[rt][j+k] = max(dp[rt][j+k],tmp[j]+dp[y][k]-tree[i].val); } } num[rt]+=num[y]; } } int main() { int i,j,k; while(~sf("%d%d",&n,&m)) { init(); for(i=1;i<=n-m;i++) { num[i] = 0; sf("%d",&k); for(j=0;j<k;j++) { int x,y; sf("%d%d",&x,&y); add(i,x,y); add(x,i,y); } } for(i=1;i<=n;i++) { for(j=1;j<=m;j++) dp[i][j] = -10000000; } for(i=n-m+1;i<=n;i++) { num[i] = 1; sf("%d",&dp[i][1]); } dfs(1); for(i=m;i>=0;i--) { if(dp[1][i]>=0) { pf("%d ",i); break; } } } }