Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 3675 | Accepted: 1936 |
Description
Input
Output
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
题意:一个树形网络,编号为1的是广播站,叶子节点为广播接收者,要想使用必须付出费用,中间的其他点是中继站,信号到达每个中继站都会有一定的消费;问在保证广播站收益不亏本的情况下使用者最多是多少? 分析:dp[i][j]表示第i个点下面有j个使用用户的收益;状态转移方程: dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]-edge[i].w); 其中u是v的父节点,j枚举u节点的所有子叶点数,k枚举v节点的所有子叶点数,edge[i].w表示u节点下的使用用户不是0的话要减去的成本 dp全部初始化为-inf,dp[i][0]赋为0;
#include"stdio.h" #include"string.h" #include"iostream" #include"map" #include"string" #include"queue" #include"stdlib.h" #include"math.h" #define eps 1e-10 #define M 3333 #define inf 99999999 #include"algorithm" #define g 9.8 #define PI acos(-1.0) using namespace std; int dp[M][M]; struct node { int v,w; node(int vv,int ww) { v=vv; w=ww; } }; vector<node>edge[M]; int cost[M],sum[M],use[M],m,n; void dfs(int u) { use[u]=1; for(int i=0;i<(int)edge[u].size();i++) { int v=edge[u][i].v; if(!use[v]) { dfs(v); sum[u]+=sum[v]; for(int j=sum[u];j>=0;j--) { for(int k=1;k<=sum[v];k++) { if(j>=k) dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]-edge[u][i].w); } } } } if(u>n-m) { sum[u]=1; dp[u][1]=cost[u]; } } int main() { int i,j,k,c; while(scanf("%d%d",&n,&m)!=-1) { for(i=1;i<=n;i++) edge[i].clear(); for(i=1;i<=n-m;i++) { scanf("%d",&k); while(k--) { scanf("%d%d",&j,&c); edge[i].push_back(node(j,c)); edge[j].push_back(node(i,c)); } } for(i=n-m+1;i<=n;i++) scanf("%d",&cost[i]); for(i=1;i<=n;i++) { dp[i][0]=0; for(j=1;j<=m;j++) dp[i][j]=-inf; } memset(sum,0,sizeof(sum)); memset(use,0,sizeof(use)); dfs(1); //for(i=1;i<=m;i++) //printf("%d ",dp[1][i]); for(i=m;i>=1;i--) { if(dp[1][i]>=0) { printf("%d\n",i); break; } } } return 0; }