POJ 1155 TELE
题目意思:
电视台发送信号给很多用户,每个用户愿意出一些钱,电视台经过的路线都有一定费用,求电视台不损失的情况下最多给多少用户发送信号。
多么明显的有依赖性的01背包:
dp[i][j]对于借点I 背包容量J ;
#include <cstdio> #include <cmath> #include <algorithm> #include <cstring> #include <cstdlib> using namespace std; const int maxn=3004; const int INF=0x7ffffff; struct Edge { int to,dis,pre; Edge(int to=0,int dis=0,int pre=0):to(to),dis(dis),pre(pre){} }; Edge edge[maxn]; int head[maxn],pos; int money[maxn]; int dp[maxn][maxn]; void inint() { memset(head,-1,sizeof(head)); pos=0; } void add_edge(int &s,int &to,int &dis) { edge[pos]=Edge(to,dis,head[s]); head[s]=pos++; } int n,m; int dfs(int s) { int ans=0,key; dp[s][0]=0; for(int i=1;i<maxn;i++)dp[s][i]=-INF; for(int i=head[s];i!=-1;i=edge[i].pre) { Edge &tmp=edge[i]; if(tmp.to==-1) key=0; else key=dfs(tmp.to); ans+=key; for(int j=ans;j>=1;j--) for(int t=1;t<=key;t++) { if(j<t)break; dp[s][j]=max(dp[s][j],dp[s][j-t]+dp[tmp.to][t]-tmp.dis); } } if(s>(n-m)) { ans++; for(int j=ans;j>=1;j--) dp[s][j]=dp[s][j-1]+money[s]; } return ans; } int main() { int num,a,b; while(~scanf("%d%d",&n,&m)) { inint(); for(int i=1;i<=(n-m);i++) { scanf("%d",&num); for(int w=1;w<=num;w++) scanf("%d%d",&a,&b), add_edge(i,a,b); } for(int i=n-m+1;i<=n;i++)scanf("%d",&money[i]); dfs(1); for(int i=n;i>=0;i--) if(dp[1][i]>=0){printf("%d\n",i);break;} } return 0; }