Codeforces Round #383 (Div. 2)D-(并查集&分组背包)|(搜索&01背包)

来源:互联网 发布:录像软件 编辑:程序博客网 时间:2024/05/17 22:29

传送门
这里写图片描述
分组背包模板题。
用并查集搞一搞一齐的关系就好。
然后就是分组背包的模板了,注意,在分组的时候,把i组所有和加起来 这一个虚拟的物品分到 i组里,而不能独立分组,不然会造成某一个模特的的多次使用。。
或者用搜索,这个搜索用滚动数组的时候,类似于树形dp里面,在一个树内进行01背包。
但是在遍历的时候,可能会出现从0数组 转到0数组的情况(1数组先前已经被vis掉了,如果我们不处理这个结果就会发生前面的结果可能没有办法继承。)所以我们每次可以 把所有的数组 都给赋值了。
这个很重要,本菜没有想到好的方法。大家可以一起交流
dfs搜索版本

#include <bits/stdc++.h>#define MOD 1000000007#define maxn 100005using namespace std;typedef long long ll;int dp[2][1005], vis[1005];int w[1005], b[1005], h, sum1, sum2;vector<int> v[1005];int n, m, ww, a, bb;void dfs(int k,int j){    for(int i = ww; i >= w[k]; i--){        dp[j%2][i] = max(dp[(j-1)%2][i-w[k]] + b[k], dp[j%2][i]);    }    vis[k] = 1;    sum1 += w[k];    sum2 += b[k];    for(int i = 0; i < v[k].size(); i++){        if(vis[v[k][i]] == 0){            dfs(v[k][i],j);        }    }}int main(){  //  freopen("in.txt", "r", stdin);    scanf("%d%d%d", &n, &m, &ww);    for(int i = 1; i <= n; i++)     scanf("%d", w+i);    for(int j = 1; j <= n; j++)     scanf("%d", b+j);    for(int i = 1; i <= m; i++){        scanf("%d%d",&a,&bb);        v[a].push_back(bb);        v[bb].push_back(a);//建图,然后用搜索的方法处理,类似树形dp    }    for(int i=1;i<=n;i++){        sum1=0;sum2=0;        //memset(vis,false,sizeof(vis));        if(!vis[i])        dfs(i,i);//一层一层的背包。        for(int j = ww; j >= sum1; j--){            dp[i%2][j] = max(dp[(i-1)%2][j-sum1] + sum2, dp[i%2][j]);          }        for(int x=1;x<=ww;x++)         dp[(i+1)%2][x]=dp[i%2][x];         // cout<<endl;    } printf("%d\n",dp[n%2][ww]);    return 0;}
#include <iostream>#include <cstdio>#include <cstdlib>#include <vector>using namespace std;/*分组背包,模板题。*/const int maxn=100005;int fa[maxn];void init(int m){for(int i=0;i<maxn;i++)    fa[i]=i;}int find1(int a){   if(fa[a]==a)return a;   return fa[a]=find1(fa[a]);}void unite(int a,int b ){   int x=find1(a);    int y=find1(b);    if(x==y)return;    fa[x]=y;}int c[maxn];int v[maxn];vector<int>G[maxn];int dp[maxn];int main(){   int m,n,p;    int a,b;    scanf("%d%d%d",&m,&n,&p);    init(m*2);    for(int i=1;i<=m;i++){        scanf("%d",&c[i]);    }    for(int i=1;i<=m;i++){        scanf("%d",&v[i]);    }    for(int i=1;i<=n;i++){        scanf("%d%d",&a,&b);        unite(a,b);    }    int t=m;    for(int i=1;i<=m;i++)        G[find1(i)].push_back(i);//根据ufs关系来确定一个图图        for(int i=1;i<=m;i++){            int sum1=0;            int sum2=0;            if(!G[i].size()) continue;            for(int j=0;j<G[i].size();j++){                sum1+=c[G[i][j]];                sum2+=v[G[i][j]];            }            if(G[i].size()<=1) continue;            c[1+t]=sum1;            v[++t]=sum2;            G[i].push_back(t);        }        /*for(int i=0;i<=t;i++){            cout<<i<<"@@";            for(int j=0;j<G[i].size();j++)             printf("%d ",G[i][j]);             cout<<endl;             }*/        //cout<<m<<endl;     for(int i=1;i<=t;i++){         if(!G[i].size()) continue;         for(int j=p;j>=0;j--){            for(int k=0;k<G[i].size();k++)                if(j>=c[G[i][k]])                dp[j]=max(dp[j],dp[j-c[G[i][k]]]+v[G[i][k]]);         }     }     printf("%d\n",dp[p]);    return 0;}
阅读全文
0 0
原创粉丝点击