[BZOJ 1312] Neerc2006 Hard Life

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;
}

猜你喜欢

转载自www.cnblogs.com/fly-in-milkyway/p/10116008.html
今日推荐