首先注意到能产生贡献的只有 \(l_i,r_i\),虽然这是废话,因为每个点都有一个唯一对应的 \(l_i\) 或 \(r_i\),但我认为刚刚的性质还是挺有用的,因为这启发我们考虑每个点的贡献,然而对于一个点可选可不选,并考虑每个的贡献,点之间有些限制,这非常网络流。
于是我们去分析这些性质,发现有包含或不交关系的点之间并不存在限制,否则才有限制。那么什么会有限制呢?其实只有当 \(l_i<l_j,r_i<r_j,r_i>l_j\) 时,\(l_j\) 和 \(r_i\) 之间才有限制,我们连接这些边,由于我们只会在 \(l\) 与 \(r\) 之间连边,所以长出来的图是个二分图,然后问题变成了求最大独立集问题,于是这道题就做完啦!
代码:
#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);
}
标签:dep,Magic,int,ret,P9726,限制,Final,define
From: https://www.cnblogs.com/lalaouyehome/p/18432525