1. 程式人生 > >CodeForces - 976F Minimal k-covering

CodeForces - 976F Minimal k-covering

clu int oid n) CP cto add 系列 %d

Description

給你一張左邊 \(n_1\) 個點,右邊 \(n_2\) 個點, \(m\) 條邊的二分圖。對於每一個 \(0\le k\le minDeg\) ,求選取哪些邊可以使每個點的度數都不小於 \(k\)

\(1\le n_1,n_2\le 2000\)\(m\le 2000\)

Solution

大力建模誰都會系列,多組詢問會炸。

於是建邊就建流量為 \(deg[i]-k\) 的邊,每次增加流量即可。

#include<bits/stdc++.h>
using namespace std;

template <class T> inline void read(T &x) {
    x = 0
; static char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar()); for (; ch >= '0' && ch <= '9'; ch = getchar()) (x *= 10) += ch - '0'; } #define N 5001 #define rep(i, a, b) for (int i = a; i <= b; i++) #define INF 0x3f3f3f3f int
S, T, head[N], cur[N], tot = 1, q[N], dep[N]; struct edge { int v, c, next; }e[100001]; inline void insert(int u, int v, int c) { e[++tot].v = v, e[tot].c = c, e[tot].next = head[u]; head[u] = tot; } inline void add(int u, int v, int c) { insert(u, v, c), insert(v, u, 0); } inline bool bfs() { memset(dep, 0
, sizeof dep); dep[S] = 1; int l = 1, r = 1; q[1] = S; while (l <= r) { int u = q[l++]; for (int i = head[u], v; i; i = e[i].next) if (e[i].c && !dep[v = e[i].v]) { dep[v] = dep[u] + 1, q[++r] = v; if (!(v ^ T)) return 1; } } return 0; } int dfs(int u, int dist) { if (u == T) return dist; int ret = 0; for (int &i = head[u], v; i; i = e[i].next) if (dep[v = e[i].v] == dep[u] + 1 && e[i].c) { int d = dfs(v, min(dist - ret, e[i].c)); e[i].c -= d, e[i ^ 1].c += d, ret += d; if (ret == dist) return dist; } if (!ret) dep[u] = -1; return ret; } inline void cpy() { rep(i, S, T) cur[i] = head[i]; } inline void rec() { rep(i, S, T) head[i] = cur[i]; } int dinic() { int ret = 0; cpy(); while (bfs()) ret += dfs(S, INF), rec(); return ret; } int nu, nv, n, m, deg[N], minDeg = INF; vector<int> ans[N]; struct Data { int u, v; }a[N]; int main() { read(nu), read(nv), read(m), n = nu + nv, T = n + 1; rep(i, 1, m) read(a[i].u), read(a[i].v), a[i].v += nu, deg[a[i].u]++, deg[a[i].v]++; rep(i, 1, n) minDeg = min(minDeg, deg[i]); rep(i, 1, nu) add(S, i, deg[i] - minDeg - 1); rep(i, nu + 1, n) add(i, T, deg[i] - minDeg - 1); int tmp = tot; rep(i, 1, m) add(a[i].u, a[i].v, 1); for (int i = minDeg; i >= 0; i--) { for (int j = 2; j <= tmp; j += 2) e[j].c++; dinic(); for (int j = tmp + 1; j <= tot; j += 2) if (e[j].c) ans[i].push_back((j - tmp + 1) / 2); } rep(i, 0, minDeg) { printf("%d ", ans[i].size()); for (auto y : ans[i]) printf("%d ", y); puts(""); } return 0; }

CodeForces - 976F Minimal k-covering