Description
最大密度子图的板子
Solution
我只是想来吐槽一下这个题(╯‵□′)╯︵┻━┻
任意两个子图的密度之差不超过 \(\dfrac{1}{n^2}\)
\(m=0\) 要输出 \(1\)
为什么直接判断端点不对
Code
#include <queue>
#include <cstdio>
#include <cstring>
const int N = 10000;
const double INF = 1e18, eps = 1e-8;
struct Edge {
int v, nxt; double c, f;
} e[N];
struct Pair {
int x, y;
} p[N];
int n, m, S, T, tot, cur[N], head[N], d[N], ans, vis[N];
double min(double x, double y) {
return x < y ? x : y;
}
void adde(int u, int v, double c) {
e[++tot].nxt = head[u], head[u] = tot, e[tot].v = v, e[tot].c = c, e[tot].f = 0;
e[++tot].nxt = head[v], head[v] = tot, e[tot].v = u, e[tot].c = 0, e[tot].f = 0;
}
int bfs() {
int vis[N] = {}; vis[S] = 1;
std::queue<int> q; q.push(S);
while (!q.empty()) {
int u = q.front(); q.pop();
for (int i = head[u]; ~i; i = e[i].nxt)
if (!vis[e[i].v] && e[i].c > e[i].f)
d[e[i].v] = d[u] + 1, vis[e[i].v] = 1, q.push(e[i].v);
}
return vis[T];
}
double dfs(int u, double a) {
if (u == T || a < eps) return a;
double flow = 0, x;
for (int &i = cur[u]; ~i; i = e[i].nxt)
if (d[u] + 1 == d[e[i].v] && (x = dfs(e[i].v, min(a, e[i].c - e[i].f))) > 0) {
e[i].f += x, e[i^1].f -= x, flow += x, a -= x;
if (a < eps) break;
}
return flow;
}
double dinic() {
double flow = 0;
while (bfs()) memcpy(cur, head, sizeof cur), flow += dfs(S, INF);
return flow;
}
void build(double k) {
tot = -1, memset(head, -1, sizeof head);
for (int i = 1; i <= m; ++i)
adde(S, n + i, 1), adde(n + i, p[i].x, INF), adde(n + i, p[i].y, INF);
for (int i = 1; i <= n; ++i) adde(i, T, k);
}
void fsd(int u) {
vis[u] = 1, ans += (u <= n);
for (int i = head[u]; ~i; i = e[i].nxt)
if (!vis[e[i].v] && e[i].c - e[i].f > eps) fsd(e[i].v);
}
int main() {
scanf("%d%d", &n, &m);
if (!m) { puts("1"); return 0; }
S = n + m + 1, T = n + m + 2;
for (int i = 1; i <= m; ++i) scanf("%d%d", &p[i].x, &p[i].y);
double l = 0, r = m, mid, res;
while (l + 1.0 / n / n < r) {
mid = (l + r) / 2;
build(mid), res = m - dinic();
if (res > 0) l = mid; else r = mid;
}
build(l), dinic(), fsd(S), printf("%d\n", ans);
return 0;
}