VijosP1250:分组背包

背景

Wind设计了很多机器人。但是它们都认为自己是最强的,于是,一场比赛开始了~

描述

机器人们都想知道谁是最勇敢的,于是它们比赛搬运一些物品。

它们到了一个仓库,里面有n个物品,每个物品都有一个价值Pi和重量Wi,但是有些物品放在一起会爆炸,并且爆炸具有传递性。(a和b会爆炸、b和c会爆炸则a和c会爆炸)
机器人们可不想因此损失自己好不容易从Wind那里敲诈来的装备,于是它们想知道在能力范围内,它们最多可以拿多少价值的物品。

你能帮助它们吗?

格式

输入格式

每组测试数据
第1行为n,Wmax,k(0<=n,Wmax,k<=1000)
接下来n行,为每个物品的Pi,Wi(0<=Pi<=1000,1<=Wi<=10,均为整数)
再接下来k行,每行2个数字a,b表示a和b会发生爆炸

输出格式

对每组数据输出1行
为最大可能价值

输入:

3 10 1
100 1
200 5
10 5
1 2

输出:

210

思路:分组背包模板题

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=1005;
int n,W,k;
int v[MAXN],w[MAXN];
int par[MAXN];
int prep()
{
    for(int i=0;i<MAXN;i++)
    {
        par[i]=i;
    }
}
int fnd(int x)
{
    if(par[x]==x)
    {
        return x;
    }
    return par[x]=fnd(par[x]);
}
void unite(int x,int y)
{
    int a=fnd(x);
    int b=fnd(y);
    par[a]=b;
}
bool same(int x,int y)
{
    return fnd(x)==fnd(y);
}
int dp[MAXN];
vector<int> vec[MAXN];
int main()
{
    scanf("%d%d%d",&n,&W,&k);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&v[i],&w[i]);
    }
    prep();
    for(int i=0;i<k;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        x--,y--;
        unite(x,y);
    }
    
    for(int i=0;i<n;i++)
    {
        int root=fnd(i);
        vec[root].push_back(i);
    }
    
    for(int k=0;k<n;k++)
    {
        if(vec[k].size()==0)
        {
            continue;
        }
        for(int j=W;j>=0;j--)
            for(int i=0;i<vec[k].size();i++)
            {
                int x=vec[k][i];
                if(j>=w[x])
                    dp[j]=max(dp[j],dp[j-w[x]]+v[x]);
            }
    }
    printf("%d\n",dp[W]);
    
    return 0;
} 

 

posted on 2016-04-07 22:01  vCoders  阅读(279)  评论(0编辑  收藏  举报

导航