标签:eve 电视 close view inf ret set 其他 code
题意:给出n个节点的树,根节点是电视台,给出m个用户,用户的编号为(n-m+1,n)
接下来给出n-m+1行,第一行就是以编号为1为向其他点连接,第二行就是以编号为2向其他点连接,以此类推
然后在处理某一行的时候,第一个数字表示有多少个儿子
然后接下来每次输入两个数,第一个为编号,第二个为边权值
最后一行给出用户给出的费用
问在不亏本的情况下所能连接的最多用户为多少
思路:不亏本,即为最后花费的钱数<=0
首先确立dp【i】【j】表示在第i颗树时,有j个用户的最少花费
那么我们遍历某个节点的时候,就从当前最大的节点数开始更新,为什么不能从最小呢?
因为倘若从最小开始的话呢,可能会重复使用某个用户(这跟背包类似)
然后逐一遍历即可
好久没有自己做出树形DP了!!!这道题让我挺开心,虽然是道没有什么修饰的题
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=3e3+10; 4 const int inf=0x3f3f3f3f; 5 int dp[maxn][maxn]; 6 struct node 7 { 8 int v,w,nxt; 9 }G[maxn]; 10 int head[maxn]; int num; 11 int sum[maxn]; 12 void add(int u,int v,int w) 13 { 14 G[++num].v=v;G[num].w=w;G[num].nxt=head[u];head[u]=num; 15 } 16 void dfs(int u) 17 { 18 // printf("u:%d\n",u); 19 for(int T=head[u];T;T=G[T].nxt){ 20 int v=G[T].v;int w=G[T].w; 21 // printf("2222222222\n"); 22 dfs(v); 23 int tmp=sum[u]+sum[v]; 24 for(int i=tmp;i>=1;i--) 25 for(int j=0;j<=sum[u];j++){ 26 int k=i-j; 27 if(k>sum[v]) continue; 28 dp[u][i]=min(dp[u][i],dp[u][j]+dp[v][k]+w); 29 // printf("dp[%d][%d]:%d\n",u,i,dp[u][i]); 30 // printf("dp[%d][1]: %d\n",v,dp[v][1]); 31 } 32 sum[u]+=sum[v]; 33 } 34 } 35 int main() 36 { 37 int n,m; 38 scanf("%d%d",&n,&m); 39 for(int i=1;i<=n-m;i++){ 40 int k; 41 scanf("%d",&k); 42 int u=i; 43 for(int j=1;j<=k;j++){ 44 int v,w; 45 scanf("%d%d",&v,&w); 46 add(u,v,w); 47 } 48 } 49 memset(dp,inf,sizeof(dp)); 50 for(int i=1;i<=n;i++) 51 dp[i][0]=0; 52 for(int i=n-m+1;i<=n;i++){ 53 int tmp; 54 scanf("%d",&tmp); 55 dp[i][1]=-tmp; 56 sum[i]=1; 57 } 58 dfs(1); 59 // printf("%d\n",dp[1][1]); 60 for(int i=m;i>=0;i--){ 61 if(dp[1][i]<=0){ 62 printf("%d\n",i); 63 break; 64 } 65 } 66 return 0; 67 }
标签:eve 电视 close view inf ret set 其他 code
原文地址:https://www.cnblogs.com/pangbi/p/12589480.html