題目:
殷犇有很多隊員。他們都認爲自己是最強的,於是,一場比賽開始了~
於是安叔主辦了一場比賽,比賽有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;
}