vijos1250 最勇敢的机器人

背景

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行
为最大可能价值

样例1

样例输入1[复制]

 
3 10 1
100 1
200 5
10 5
1 2

样例输出1[复制]

 
210
/*
并查集分组,分组背包
*/
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 1005;
struct ITM{
    int v;
    int w;
}temp;
int n,c,k,f[maxn],v[maxn],w[maxn],dp[maxn];
int u1,u2,r;
int cnt,tran[maxn],now;
bool vis[maxn];
vector<ITM> itm[maxn];
int findf(int x){
    return x == f[x] ? x : f[x] = findf(f[x]);
}
int read(){
    char ch=getchar();
    int f=1,x=0;
    while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();};
    while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();};
    return x*f;
}
int main(){
    n = read();
    c = read();
    k = read();
    for(int i = 1;i <= n;i++) f[i] = i;
    for(int i = 1;i <= n;i++){
        v[i] = read();
        w[i] = read();
    }
    for(int i = 1;i <= k;i++){
        u1 = read();
        u2 = read();
        u1 = findf(u1);
        u2 = findf(u2);
        if(u1 != u2) f[u1] = u2;
    }
    for(int i = 1;i <= n;i++){
        r = findf(i);
        temp.v = v[i];
        temp.w = w[i];
        itm[r].push_back(temp);
        if(!vis[r]){
            vis[r] = true;
            cnt++;
            tran[cnt] = r;
        }
    }
    for(int i = 1;i <= cnt;i++){
        now = tran[i];
        for(int j = c;j >= 0;j--){
            for(int t = 0;t < itm[now].size();t++){
                if(j >= itm[now][t].w)dp[j] = max(dp[j],dp[j-itm[now][t].w] + itm[now][t].v);
            }
        }
    }
    cout<<dp[c];
    return 0;
}

 

posted @ 2016-09-21 19:00  ACforever  阅读(406)  评论(0编辑  收藏  举报