1. 程式人生 > >Codeforces Round #383 (Div. 2)D-(並查集&分組揹包)|(搜尋&01揹包)

Codeforces Round #383 (Div. 2)D-(並查集&分組揹包)|(搜尋&01揹包)

傳送門
這裡寫圖片描述
分組揹包模板題。
用並查集搞一搞一齊的關係就好。
然後就是分組揹包的模板了,注意,在分組的時候,把i組所有和加起來 這一個虛擬的物品分到 i組裡,而不能獨立分組,不然會造成某一個模特的的多次使用。。
或者用搜索,這個搜尋用滾動陣列的時候,類似於樹形dp裡面,在一個樹內進行01揹包。
但是在遍歷的時候,可能會出現從0陣列 轉到0陣列的情況(1陣列先前已經被vis掉了,如果我們不處理這個結果就會發生前面的結果可能沒有辦法繼承。)所以我們每次可以 把所有的陣列 都給賦值了。
這個很重要,本菜沒有想到好的方法。大家可以一起交流
dfs搜尋版本

#include <bits/stdc++.h>
#define MOD 1000000007 #define maxn 100005 using 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;
}