60 分求助
  • 板块P2170 选学霸
  • 楼主wtxy2006
  • 当前回复12
  • 已保存回复12
  • 发布时间2020/6/7 21:48
  • 上次更新2023/11/7 01:00:27
查看原帖
60 分求助
289573
wtxy2006楼主2020/6/7 21:48

RT,用的是并查集加二进制拆分的多重背包,为什么错了呢?

// P2170 选学霸
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#define MN 200005
using namespace std;
inline int read() {
  int x = 0, f = 1;
  char ch = getchar();
  while (ch < '0' || ch > '9') {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (ch >= '0' && ch <= '9')
    x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
  return x * f;
}
struct thing {
  int v, m;
} things[MN];
int n, m, k;
int fa[MN], g[MN], vis[MN];
int cnt, s[MN], dp[MN], tot;
int find(int x) {
  while (x != fa[x]) x = fa[x] = fa[fa[x]];
  return fa[x];
}
int main() {
  int a, b;
  freopen("/mnt/d/workspace/Exercise/data/P2170_2.in", "r", stdin);
  n = read(), m = read(), k = read();
  for (int i = 1; i <= n; i++) fa[i] = i, g[i] = 1;
  for (int i = 0; i < k; i++) {
    a = find(read()), b = find(read());
    fa[a] = b, g[b] += g[a];
  }
  for (int i = 1; i <= n; i++)
    if (!vis[find(i)]) vis[find(i)] = 1, s[cnt++] = g[find(i)];
  sort(s, s + cnt), a = s[0], b = 1;
  for (int i = 1; i <= cnt; i++)
    if (a != s[i])
      things[tot++] = thing{a, b}, a = s[i], b = 0;
    else
      b++;
  dp[0] = 1;
  for (int i = 0; i < tot; i++) {
    int now = 1, temp = things[i].m, a = things[i].v;
    while (1)
      if (temp > now) {
        temp -= now;
        for (int j = m * 2; j >= now * a; j--)
          if (dp[j - now * a]) dp[j] = 1;
        now *= 2;
      } else {
        for (int j = m * 2; j >= temp * a; j--)
          if (dp[j - temp * a]) dp[j] = 1;
        break;
      }
  }
  for (int i = m, j = m; i >= 0; i--, j++)
    if (dp[i]) {
      printf("%d", i);
      return 0;
    } else if (dp[j]) {
      printf("%d", j);
      return 0;
    }
  return 0;
}
2020/6/7 21:48
加载中...