UvaLive 3709 Hard Life(最大密度子图)

来源:互联网 发布:sqlmap mssql注入步骤 编辑:程序博客网 时间:2024/05/03 22:09

题目大意:求出最大的密度子图

解题思路:详见胡伯涛:算法合集之《最小割模型在信息学竞赛中的应用》

第一种解法,最大权闭合的解法

#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>using namespace std;#define N 1110const double INF = 0x3fffffff;const int D_INF = 0x3f3f3f3f;const double esp = 1e-8;struct Edge {    int from, to;    double cap, flow;    Edge() {}    Edge(int from, int to, double cap, double flow): from(from), to(to), cap(cap), flow(flow) {}};struct ISAP {    int p[N], num[N], cur[N], d[N];    int t, s, n, m;    bool vis[N];    vector<int> G[N];    vector<Edge> edges;    void init(int n) {        this->n = n;        for (int i = 0; i <= n; i++) {            G[i].clear();            d[i] = D_INF;        }        edges.clear();    }    void AddEdge(int from, int to, double cap) {        edges.push_back(Edge(from, to, cap, 0));        edges.push_back(Edge(to, from, 0, 0));        m = edges.size();        G[from].push_back(m - 2);        G[to].push_back(m - 1);    }    bool BFS() {        memset(vis, 0, sizeof(vis));        queue<int> Q;        d[t] = 0;        vis[t] = 1;        Q.push(t);        while (!Q.empty()) {            int u = Q.front();            Q.pop();            for (int i = 0; i < G[u].size(); i++) {                Edge &e = edges[G[u][i] ^ 1];                if (!vis[e.from] && e.cap - e.flow > esp) {                    vis[e.from] = true;                    d[e.from] = d[u] + 1;                    Q.push(e.from);                }            }        }        return vis[s];    }    double Augment() {        int u = t;        double flow = INF;        while (u != s) {            Edge &e = edges[p[u]];            flow = min(flow, e.cap - e.flow);            u = edges[p[u]].from;        }        u = t;        while (u != s) {            edges[p[u]].flow += flow;            edges[p[u] ^ 1].flow -= flow;            u = edges[p[u]].from;        }        return flow;    }    double Maxflow(int s, int t) {        this->s = s; this->t = t;        double flow = 0;        BFS();        if (d[s] > n)            return 0;        memset(num, 0, sizeof(num));        memset(cur, 0, sizeof(cur));        for (int i = 0; i < n; i++)            if (d[i] < D_INF)                num[d[i]]++;        int u = s;        while (d[s] <= n) {            if (u == t) {                flow += Augment();                u = s;            }            bool ok = false;            for (int i = cur[u]; i < G[u].size(); i++) {                Edge &e = edges[G[u][i]];                if (e.cap - e.flow > esp && d[u] == d[e.to] + 1) {                    ok = true;                    p[e.to] = G[u][i];                     cur[u] = i;                    u = e.to;                    break;                }            }            if (!ok) {                int Min = n;                for (int i = 0; i < G[u].size(); i++) {                    Edge &e = edges[G[u][i]];                    if (e.cap - e.flow > esp)                        Min = min(Min, d[e.to]);                }                if (--num[d[u]] == 0)                    break;                num[d[u] = Min + 1]++;                cur[u] = 0;                if (u != s)                    u = edges[p[u]].from;            }        }        return flow;    }};ISAP isap;#define maxn 1010int n, m, source, sink, Sum;int x[maxn], y[maxn];bool vis[maxn];void init() {    for (int i = 1; i <= m; i++)        scanf("%d%d", &x[i], &y[i]);}void build(double mid) {    isap.init(sink);    for (int i = 1; i <= m; i++) {        isap.AddEdge(source, n + i, 1.0);        isap.AddEdge(n + i, x[i], INF);        isap.AddEdge(n + i, y[i], INF);    }    for (int i = 1; i <= n; i++) isap.AddEdge(i, sink, mid);}void dfs(int u) {    vis[u] = true;    if (u >= 1 && u <= n) Sum++;    for (int i = 0; i < isap.G[u].size(); i++) {        Edge &e = isap.edges[isap.G[u][i]];        if (!vis[e.to] && e.cap - e.flow > esp) dfs(e.to);    }}void solve() {    double l = 0, r = m, mid, ans;    source = 0, sink = n + m + 1;    while (r - l >= 1.0 / n / n) {        mid = (l + r) / 2;        build(mid);        ans = isap.Maxflow(source, sink);        if (1.0 * m - ans < esp) r = mid;        else l = mid;    }    build(l);    isap.Maxflow(source, sink);    memset(vis, 0, sizeof(vis));    Sum = 0;    dfs(source);    printf("%d\n", Sum);    for (int i = 1; i <= n; i++)        if (vis[i])            printf("%d\n", i);}int main() {    while (scanf("%d%d", &n, &m) != EOF) {        if (!m) {            printf("1\n1\n");            continue;        }        init();        solve();    }    return 0;}

第二种解法:

#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>using namespace std;#define N 1110#define INF 0x3f3f3f3fconst double Max = 0x3fffffff;const double esp = 1e-8;struct Edge {    int from, to;    double cap, flow;    Edge() {}    Edge(int from, int to, double cap, double flow): from(from), to(to), cap(cap), flow(flow) {}};struct ISAP {    int p[N], num[N], cur[N], d[N];    int t, s, n, m;    bool vis[N];    vector<int> G[N];    vector<Edge> edges;    void init(int n) {        this->n = n;        for (int i = 0; i <= n; i++) {            G[i].clear();            d[i] = INF;        }        edges.clear();    }    void AddEdge(int from, int to, double cap) {        edges.push_back(Edge(from, to, cap, 0));        edges.push_back(Edge(to, from, 0, 0));        m = edges.size();        G[from].push_back(m - 2);        G[to].push_back(m - 1);    }    bool BFS() {        memset(vis, 0, sizeof(vis));        queue<int> Q;        d[t] = 0;        vis[t] = 1;        Q.push(t);        while (!Q.empty()) {            int u = Q.front();            Q.pop();            for (int i = 0; i < G[u].size(); i++) {                Edge &e = edges[G[u][i] ^ 1];                if (!vis[e.from] && e.cap - e.flow > esp) {                    vis[e.from] = true;                    d[e.from] = d[u] + 1;                    Q.push(e.from);                }            }        }        return vis[s];    }    double Augment() {        int u = t;        double flow = Max;        while (u != s) {            Edge &e = edges[p[u]];            flow = min(flow, e.cap - e.flow);            u = edges[p[u]].from;        }        u = t;        while (u != s) {            edges[p[u]].flow += flow;            edges[p[u] ^ 1].flow -= flow;            u = edges[p[u]].from;        }        return flow;    }    double Maxflow(int s, int t) {        this->s = s; this->t = t;        double flow = 0;        BFS();        if (d[s] > n)            return 0;        memset(num, 0, sizeof(num));        memset(cur, 0, sizeof(cur));        for (int i = 0; i < n; i++)            if (d[i] < INF)                num[d[i]]++;        int u = s;        while (d[s] <= n) {            if (u == t) {                flow += Augment();                u = s;            }            bool ok = false;            for (int i = cur[u]; i < G[u].size(); i++) {                Edge &e = edges[G[u][i]];                if (e.cap - e.flow > esp && d[u] == d[e.to] + 1) {                    ok = true;                    p[e.to] = G[u][i];                     cur[u] = i;                    u = e.to;                    break;                }            }            if (!ok) {                int Min = n;                for (int i = 0; i < G[u].size(); i++) {                    Edge &e = edges[G[u][i]];                    if (e.cap - e.flow > esp)                        Min = min(Min, d[e.to]);                }                if (--num[d[u]] == 0)                    break;                num[d[u] = Min + 1]++;                cur[u] = 0;                if (u != s)                    u = edges[p[u]].from;            }        }        return flow;    }};ISAP isap;#define maxn 1010#define maxm 110int n, m, source, sink, Sum;int x[maxn], y[maxn], in[maxm];bool vis[maxm];void init() {    memset(in, 0, sizeof(in));    for (int i = 1; i <= m; i++) {        scanf("%d%d", &x[i], &y[i]);        in[x[i]]++; in[y[i]]++;    }}void build(double mid) {    isap.init(sink);    for (int i = 1; i <= n; i++) {        isap.AddEdge(source, i, m * 1.0);        isap.AddEdge(i, sink, m + 2 * mid - in[i]);    }    for (int i = 1; i <= m; i++) {        isap.AddEdge(x[i], y[i], 1.0);        isap.AddEdge(y[i], x[i], 1.0);    }}void dfs(int u) {    vis[u] = true;    if (u != source || u != sink) Sum++;    for (int i = 0; i < isap.G[u].size(); i++) {        Edge &e = isap.edges[isap.G[u][i]];        if (!vis[e.to] && e.cap - e.flow > esp)             dfs(e.to);    }}void solve() {    source = 0, sink = n + 1;    double l = 0, r = m, mid, ans;    while (r - l >= 1.0/n/n) {        mid = (r + l) / 2;        build(mid);        ans = isap.Maxflow(source, sink);        if ((1.0 * n * m - ans) / 2 > esp) l = mid;        else r = mid;       }    build(l);    isap.Maxflow(source, sink);    memset(vis, 0, sizeof(vis));    Sum = 0;    dfs(source);    printf("%d\n", Sum - 1);    for (int i = 1; i <= n; i++)        if (vis[i])            printf("%d\n", i);}int main() {    while (scanf("%d%d", &n, &m) != EOF) {        if (!m) {            printf("1\n1\n");            continue;        }        init();        solve();    }    return 0;}
0 0
原创粉丝点击