csu 10月 月赛 I 题 The Contest

Description

  殷犇有很多队员。他们都认为自己是最强的,于是,一场比赛开始了~

  于是安叔主办了一场比赛,比赛有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


  CSU_WJQ

 

Source

 
并查集+多重背包
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define maxn 1005
 5 using namespace std;
 6  
 7 int f[maxn],value[maxn],consume[maxn],dp[maxn],zu[maxn];
 8 bool vis[maxn];
 9 int find(int x)
10 {
11     int tmp=x;
12     while(x!=f[x])x=f[x];
13     while(f[tmp]!=x)
14     {
15         int y=tmp;
16         f[y]=x;
17         tmp=f[tmp];
18     }
19     return x;
20 }
21  
22 int main()
23 {
24     int n,w,k,x,y,a,b;
25     while(scanf("%d%d%d",&n,&w,&k)!=EOF)
26     {
27         memset(dp,0,sizeof dp);
28         memset(vis,0,sizeof vis);
29         for(int i=1; i<=n; i++)
30         {
31             f[i]=i;
32             scanf("%d%d",&value[i],&consume[i]);
33         }
34         for(int i=1; i<=k; i++)
35         {
36             scanf("%d%d",&x,&y);
37             int a=find(x);
38             int b=find(y);
39             f[b]=a;
40         }
41         for(int i=1; i<=n; i++)
42             find(i);
43         int tot=0,mark;
44         while(1)
45         {
46             for(int i=1; i<=n; i++)
47             {
48                 if(f[i]>0)
49                 {
50                     mark=f[i];
51                     break;
52                 }
53             }
54             for(int k=w; k>=0; k--)
55                 for(int j=1; j<=n; j++)
56                     if(f[j]==mark)
57                     {
58                         if(k>=consume[j])
59                             dp[k]=max(dp[k],dp[k-consume[j]]+value[j]);
60                     }
61             for(int i=1; i<=n; i++)
62                 if(f[i]==mark)
63                 {
64                     f[i]=0;
65                     tot++;
66                 }
67             if(tot==n)break;
68         }
69         printf("%d\n",dp[w]);
70     }
71 }
View Code

 

posted @ 2013-10-04 13:22  Yours1103  阅读(217)  评论(0编辑  收藏  举报