P1273 有线电视网
/* tree root->若干个转播站->若干个用户终端 每条边wi 每个终端vali*1 成本==sum(vali*1)-sum wi 问成本>=0 人数最大值 1.分组DP 每一个问题都可以拆分成若干子问题 dp[u][i]表示i节点,选j个用户,能得到的钱的最大值 root / / \ / \ \ 把每个节点看成一个背包啦,它的容量就是以这个节点为根的子树大小,可以选/不选 组数就是连接的子节点个数。 每组都有很多选择,选一个,两个,三个用户终端,把这些选择当做组中的元素就好了,容易看出每组中只能选一个元素 2.树形DP
但是 sum>= 由定义可知 否则多次多次更新
*/ /* 5 3 2 2 2 5 3 2 3 2 4 3 3 4 2
2
*/ #include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<string.h> #include<queue> #include<vector> #include<bits/stdc++.h> #define ll long long #define ddd printf("-----------------------\n"); using namespace std; const int maxn=3e3 +10; const int mod=998244353; const int inf=0x3f3f3f3f; int n,m,dp[maxn][maxn],val[maxn]; int head[maxn],to[maxn],nxt[maxn],w[maxn],tot; void add(int a,int b,int val){ to[++tot]=b,nxt[tot]=head[a],head[a]=tot,w[tot]=val; } int dfs(int u) { if(u>n-m){ dp[u][1]=val[u]; return 1; } int sum=0,tmp=0; for(int i=head[u];i;i=nxt[i]) { int v=to[i]; tmp=dfs(v),sum+=tmp; for(int j=sum;j>0;j--) { for(int k=1;k<=tmp;k++) { if(j>=k)dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]-w[i]); } } } return sum; } int main() { ios::sync_with_stdio(false); memset(dp,-inf,sizeof(dp)); cin>>n>>m; for(int i=1;i<=n-m;i++){ int tmp,v,w;cin>>tmp; for(int j=1;j<=tmp;j++) cin>>v>>w,add(i,v,w); } for(int i=n-m+1;i<=n;i++) cin>>val[i]; for(int i=1;i<=n;i++) dp[i][0]=0; dfs(1); for(int i=m;i>=1;i--){ if(dp[1][i]>=0){ cout<<i<<'\n'; return 0; } } return 0; }
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int N=3010; int n,m,EdgeCnt=0; int dp[N][N],val[N],a[N],t[N]; struct Edge{ int to,w,next; }e[N*N]; int read(){ int x=0,f=1;char ch=getchar(); while (ch<'0' || ch>'9'){if (ch=='-')f=-1;ch=getchar();} while ('0'<=ch && ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} return x*f; } void addedge(int u,int v,int w){ int p=++EdgeCnt; e[p].to=v;e[p].w=w;e[p].next=a[u]; a[u]=p; } int dfs(int u){ if (u>n-m){ dp[u][1]=val[u]; return 1; } int sum=0; for (int p=a[u];p;p=e[p].next){ int v=e[p].to; int tk=dfs(v); for (int j=0;j<=sum;j++)t[j]=dp[u][j]; for (int j=0;j<=sum;j++) for (int k=0;k<=tk;k++) dp[u][j+k]=max(dp[u][j+k],t[j]+dp[v][k]-e[p].w); sum+=tk; } return sum; } int main(){ n=read(),m=read(); memset(dp,~0x3f,sizeof(dp)); for (int u=1;u<=n-m;u++){ int size=read(); for (int j=1;j<=size;j++){ int v=read(),w=read(); addedge(u,v,w); } } for (int i=n-m+1;i<=n;i++) val[i]=read(); for (int i=1;i<=n;i++) dp[i][0]=0; dfs(1); for (int i=m;i>0;i--) if (dp[1][i]>=0){ printf("%d",i); break; } return 0; }

浙公网安备 33010602011771号