Loading

P9726 [EC Final 2022] Magic

首先注意到能产生贡献的只有 li,ri,虽然这是废话,因为每个点都有一个唯一对应的 liri,但我认为刚刚的性质还是挺有用的,因为这启发我们考虑每个点的贡献,然而对于一个点可选可不选,并考虑每个的贡献,点之间有些限制,这非常网络流。

于是我们去分析这些性质,发现有包含或不交关系的点之间并不存在限制,否则才有限制。那么什么会有限制呢?其实只有当 li<lj,ri<rj,ri>lj 时,ljri 之间才有限制,我们连接这些边,由于我们只会在 lr 之间连边,所以长出来的图是个二分图,然后问题变成了求最大独立集问题,于是这道题就做完啦!

代码:

#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = l; i <= r; ++ i)
#define rrp(i, l, r) for (int i = r; i >= l; -- i)
#define pii pair <int, int>
#define eb emplace_back
#define inf 1000000000
#define id(x, y) n * (x - 1) + y
#define ls p << 1
#define rs ls | 1
using namespace std;
constexpr int N = 1e4 + 5, M = (1ll << 31) - 1, P = 1e9 + 7;
constexpr double PI = acos (-1.0);
inline int rd () {
  int x = 0, f = 1;
  char ch = getchar ();
  while (! isdigit (ch)) {
    if (ch == '-') f = -1;
    ch = getchar ();
  }
  while (isdigit (ch)) {
    x = (x << 1) + (x << 3) + ch - 48;
    ch = getchar ();
  }
  return x * f;
}
int qpow (int x, int y) {
  int ret = 1;
  for (; y; y >>= 1, x = x * x % P) if (y & 1) ret = ret * x % P;
  return ret;
}
void add (int &x, int y) {
  x += y;
  if (x >= P) x -= P;
}
int n;
int l[N], r[N];
bitset <N> e[N];
int dep[N];
queue <int> q;
bool bfs () {
  rep (i, 0, n * 2 + 1) dep[i] = 0;
  dep[0] = 1;
  q.push (0);
  while (! q.empty ()) {
    int u = q.front ();
    q.pop ();
    for (int v = e[u]._Find_first (); v <= n * 2 + 1; v = e[u]._Find_next (v)) {
      if (dep[v]) continue;
      dep[v] = dep[u] + 1; q.push (v);
    }
  } return dep[n * 2 + 1];
}
int dfs (int u, int f) {
  if (u == n * 2 + 1) return f;
  int out = 0;
  for (int v = e[u]._Find_first (); v <= n * 2 + 1 && f; v = e[u]._Find_next (v)) {
    if (dep[v] != dep[u] + 1) continue;
    int tmp = dfs (v, min (1, f));
    if (tmp) e[u][v] = 0, e[v][u] = 1;
    out += tmp, f -= tmp;
  }
  if (! out) dep[u] = 0;
  return out;
}
bool pos[N];
int main () {
  // freopen ("1.in", "r", stdin);
  // freopen ("1.out", "w", stdout);
  n = rd ();
  rep (i, 1, n) {
    l[i] = rd (), r[i] = rd ();
    pos[r[i]] = 1;
  }
  rep (i, 1, n * 2) {
    if (! pos[i]) e[0][i] = 1;
    if (pos[i]) e[i][n * 2 + 1] = 1;
  }
  rep (i, 1, n) {
    rep (j, 1, n) {
      if (l[i] >= l[j]) continue;
      if (r[i] > l[j] && r[i] < r[j]) e[l[j]][r[i]] = 1;
    }
  }
  int ret = 0;
  while (bfs ()) ret += dfs (0, inf);
  printf ("%d\n", n * 2 - ret);
}

作者:lalaouye

出处:https://www.cnblogs.com/lalaouyehome/p/18432525

版权:本作品采用「114514」许可协议进行许可。

posted @   lalaouye  阅读(15)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
历史上的今天:
2023-09-25 组合数学学习笔记
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示