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;
}
dp[i+j]

 

posted @ 2023-11-09 05:22  JMXZ  阅读(11)  评论(0)    收藏  举报