The contest———CSU - 1326(分組揹包、並查集)

題目:

  殷犇有很多隊員。他們都認爲自己是最強的,於是,一場比賽開始了~

  於是安叔主辦了一場比賽,比賽有n個題目,每個題目都有一個價值Pi和相對能力消耗Wi,但是有些題目因爲太坑不能同時做出來,並且坑題具有傳遞性。(a和b一起做會坑、b和c會坑則a和c也會坑) ACM隊員們想知道,於是他們想知道在能力範圍內,它們最多可以作出多少價值的題目。

  聰明的你,告訴我,能幫幫他們嗎?

Input

  第1行兩個整數,n,Wmax,k(0<=n,Wmax,k<=1000),其中n爲題目總數,Wmax爲初始的總能力數.

  接下來n行,爲每個題目的Pi,Wi(0<=Pi<=1000,1<=Wi<=10,均爲整數)

  再接下來k行,每行2個數字a,b表示a和b會坑

Output

  對每組數據輸出1行爲最大可能價值

Sample Input

3 10 1
100 1
200 5
10 5
1 2

Sample Output

210

Hint

  每個測試點1s

  

思路:

利用並查集先把組分出來,然後進行分組揹包。

 

代碼:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int book[1010],dp[1010];
struct node
{
    int f,p,w;
}a[1010],b[1010];
int getf(int x)
{
    if(a[x].f==x)
        return x;
    return a[x].f=getf(a[x].f);
}
void link(int x,int y)
{
    int t1=getf(a[x].f);
    int t2=getf(a[y].f);
    if(t1!=t2)
        a[t2].f=t1;
}
int main()
{
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
    {
        a[i].f=i;
        scanf("%d%d",&a[i].p,&a[i].w);
    }
    for(int i=0;i<k;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        link(x,y);
    }
    for(int i=1;i<=n;i++)
    {
        b[i].f=a[i].f;
        b[i].w=a[i].w;
        b[i].p=a[i].p;
        book[b[i].f]=1;
    }
    for(int i=1;i<=n;i++)
    {
        if(!book[i])
            continue;
        for(int k=m;k>=0;k--)
        {
            for(int j=1;j<=n;j++)
            {
                if(k>=b[j].w&&b[j].f==i)
                    dp[k]=max(dp[k],dp[k-b[j].w]+b[j].p);
            }
        }
    }
    printf("%d\n",dp[m]);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章