vijos 1250 最勇敢的机器人 分组背包+并查集

P1250最勇敢的机器人

背景

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

限制

每个测试点1s

思路:用并查集分组,分组背包板子;

#include<cstdio>
#include<string>
#include<queue>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define esp 0.00000000001
const int N=1e3+10,M=1e6+10,inf=1e9+10,mod=1000000007;
int v[N],w[N];
int dp[N];
int father[N];
int zu;
int flag[N];
int m[N][N];
int s[N];
int maxx(int x,int y)
{
    return x>y?x:y;
}
int findfa(int x)
{
    return x==father[x]?x:father[x]=findfa(father[x]);
}
void he(int u,int v)
{
    int x=findfa(u);
    int y=findfa(v);
    if(x!=y)
    {
        father[x]=y;
    }
}
void initt(int x)
{
    zu=1;
    for(int i=1;i<=x;i++)
    {
        int v=findfa(i);
        if(flag[v]==0)
        flag[v]=zu++;
        m[flag[v]][s[flag[v]]++]=i;
    }
}
int main()
{
    int x,y,z,i,t,j;
    scanf("%d%d%d",&x,&y,&z);
    for(i=0;i<=x;i++)
    father[i]=i;
    for(i=1;i<=x;i++)
    scanf("%d%d",&v[i],&w[i]);
    for(i=1;i<=z;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        he(u,v);
    }
    initt(x);
    for(i=1;i<zu;i++)
    {
        for(t=y;t>=0;t--)
        {
            for(j=0;j<s[i];j++)
            if(t>=w[m[i][j]])dp[t]=maxx(dp[t],dp[t-w[m[i][j]]]+v[m[i][j]]);
        }
    }
    printf("%d\n",dp[y]);
    return 0;
}

 

posted @ 2016-08-08 10:52  jhz033  阅读(353)  评论(0编辑  收藏  举报