zoukankan      html  css  js  c++  java
  • Codeforces 741B:Arpa's weak amphitheater and Mehrdad's valuable Hoses(01背包+并查集)

    http://codeforces.com/contest/741/problem/B

    题意:有 n 个人,每个人有一个花费 w[i] 和价值 b[i],给出 m 条边,代表第 i 和 j 个人是一个集合的,给出一个最大花费 w,如果一个集合的人不能同时选的话,那么只能选集合中的其中一个或者不选,问按照这样的规则选得的花费不超过 w 的最大价值是多少。

    思路:一开始搞个带权并查集出来,后来还是蒙了。之后看原来是01背包,然而已经N久没见过背包了。。。先用并查集弄出集合,然后对每个集合中的元素进行01背包(选集合中的一个或者不选的情况),在集合弄完之后还要对整体进行01背包(选集合中的全部),这里用了下滚动数组。

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <string>
     6 #include <cmath>
     7 #include <queue>
     8 #include <vector>
     9 using namespace std;
    10 #define INF 0x3f3f3f3f
    11 #define N 100010
    12 int dp[2][1010];
    13 int fa[1010];
    14 int b[1010], w[1010];
    15 vector<int> vec[1010];
    16 
    17 int Find(int x) {
    18     if(x == fa[x]) return x;
    19     return fa[x] = Find(fa[x]);
    20 }
    21 
    22 int main()
    23 {
    24     int n, m, x;
    25     scanf("%d%d%d", &n, &m, &x);
    26     for(int i = 1; i <= n; i++) scanf("%d", w + i);
    27     for(int i = 1; i <= n; i++) scanf("%d", b + i);
    28     for(int i = 1; i <= n; i++) fa[i] = i;
    29     for(int i = 0; i < m; i++) {
    30         int u, v;
    31         scanf("%d%d", &u, &v);
    32         u = Find(u), v = Find(v);
    33         if(u != v) fa[u] = v;
    34     }
    35     for(int i = 1; i <= n; i++)
    36         vec[Find(i)].push_back(i);
    37     int now = 0;
    38     for(int i = 1; i <= n; i++) {
    39         now = !now;
    40         int ww = 0, bb = 0;
    41         for(int j = 0; j <= x; j++) dp[now][j] = dp[!now][j];
    42         for(int j = 0; j < vec[i].size(); j++) {
    43             int id = vec[i][j];
    44             int www = w[id], bbb = b[id];
    45             ww += www, bb += bbb;
    46             for(int j = www; j <= x; j++) { // 在当前集合选一个最优
    47                 dp[now][j] = max(dp[now][j], dp[!now][j-www] + bbb);
    48             }
    49         }
    50         for(int j = ww; j <= x; j++) { // 如果全部能丢进去
    51             dp[now][j] = max(dp[now][j], dp[!now][j-ww] + bb);
    52         }
    53     }
    54     int ans = 0;
    55     for(int i = 0; i <= x; i++) ans = max(ans, dp[now][i]);
    56     printf("%d
    ", ans);
    57     return 0;
    58 }
  • 相关阅读:
    fullCalendar改造计划之带农历节气节假日的万年历(转)
    Linked List Cycle
    Remove Nth Node From End of List
    Binary Tree Inorder Traversal
    Unique Binary Search Trees
    Binary Tree Level Order Traversal
    Binary Tree Level Order Traversal II
    Plus One
    Remove Duplicates from Sorted List
    Merge Two Sorted Lists
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6141048.html
Copyright © 2011-2022 走看看