[刷题]HDU3157

来源:互联网 发布:上海雨人软件 编辑:程序博客网 时间:2024/05/29 04:24

两道有上下界有源汇最小流。
步骤之前写的笔记里有。但是原理。。。确实不太懂。
步骤:
1. 按照无源汇有上下界的最大流的做法找出可行流(但不要建立t->s);
2. 添加t->s,流量上界INF;
3. 再次运行最大流,找出ss->st可行流;
4. 若ss不满载,则无可行流。反之,最小流为t->s的流量,每条边的流量为逆向边的流量(加上下界b)。

SGU176 - Flow construction

//下界网络流#include<iostream>#include<queue>#include<vector>#include<cstring>#include<algorithm>#define INF 0x3f3f3f3f#define Maxn 200using namespace std;struct Edge {    int c, f, id;    unsigned v, flip;    Edge(unsigned v, int c, int f, unsigned flip, int id) :v(v), c(c), f(f), flip(flip), id(id) {}};class Dinic {public:    bool b[Maxn];    int a[Maxn];    unsigned p[Maxn], cur[Maxn], d[Maxn];    vector<Edge> G[Maxn];    unsigned s, t;    void Init(unsigned n) {        for (int i = 0; i <= n; ++i)            G[i].clear();    }    void AddEdge(unsigned u, unsigned v, int c, int id) {        G[u].push_back(Edge(v, c, 0, G[v].size(),0));        G[v].push_back(Edge(u, 0, 0, G[u].size() - 1, id)); // 使用无向图时将0改为c即可    }    bool BFS() {        unsigned u, v;        queue<unsigned> q;        memset(b, 0, sizeof(b));        q.push(s);        d[s] = 0;        b[s] = 1;        while (!q.empty()) {            u = q.front();            q.pop();            for (auto it = G[u].begin(); it != G[u].end(); ++it) {                Edge &e = *it;                if (!b[e.v] && e.c>e.f) {                    b[e.v] = 1;                    d[e.v] = d[u] + 1;                    q.push(e.v);                }            }        }        return b[t];    }    int DFS(unsigned u, int a) {        if (u == t || a == 0)            return a;        int flow = 0, f;        for (unsigned &i = cur[u]; i<G[u].size(); ++i) {            Edge &e = G[u][i];            if (d[u] + 1 == d[e.v] && (f = DFS(e.v, min(a, e.c - e.f)))>0) {                a -= f;                e.f += f;                G[e.v][e.flip].f -= f;                flow += f;                if (!a) break;            }        }        return flow;    }    int MaxFlow(unsigned s, unsigned t) {        int flow = 0;        this->s = s;        this->t = t;        while (BFS()) {            memset(cur, 0, sizeof(cur));            flow += DFS(s, INF);        }        return flow;    }};int Flow[10000+23];int N, M;int Dif[Maxn];int main() {    ios::sync_with_stdio(false);    while (cin >> N >> M) {        const int ss = N + 1, st = N + 2;        memset(Dif, 0, sizeof(Dif));        memset(Flow, 0, sizeof(Flow));        Dinic Din;        Din.Init(N);        int u, v, b, c;        for (int i = 1; i <= M; ++i) {            cin >> u >> v >> c >> b;            if (b) {                b = c;                Dif[u] -= b;                Dif[v] += b;                Flow[i] = b;            }            else Din.AddEdge(u, v, c - b, i);        }        int sum = 0;        for (int i = 1; i <= N; ++i) {            if (Dif[i] > 0) {                Din.AddEdge(ss, i, Dif[i], 0);                sum += Dif[i];            }            if (Dif[i] < 0) Din.AddEdge(i, st, -Dif[i], 0);        }        int ans = Din.MaxFlow(ss, st);        Din.AddEdge(N, 1, INF, 0);        ans += Din.MaxFlow(ss, st);        if (sum != ans) cout << "Impossible\n";        else {            cout << Din.G[N].rbegin()->f << '\n';            for (int i = 1; i <= N; ++i) for (const auto &e : Din.G[i]) {                if (e.id) Flow[e.id] += -e.f;            }            for (int i = 1; i < M; ++i) cout << Flow[i] << ' ';            cout << Flow[M] << '\n';        }    }    return 0;}

HDU3157 - Crazy Circuits

#include<algorithm>#include<cstring>#include<cstdio>#include<cctype>#include<vector>#include<queue>#include<map>using namespace std;#define INF 0x3f3f3f3fconst int Maxn = 100;int N, M, S, T, SS, ST;int Dif[Maxn];bool QIn(int &x) {    char c;    while ((c = getchar()) != EOF && (!isdigit(c) && (c != '+'&&c != '-')));    switch (c) {    case '+':x = S; return true;    case '-':x = T; return true;    case EOF: return false;    }    x = 0;    do {        x *= 10;        x += c - '0';    } while ((c = getchar()) != EOF&&isdigit(c));    return true;}struct Edge {    int c, f;    unsigned v, flip;    Edge(unsigned v, int c, int f, unsigned flip) :v(v), c(c), f(f), flip(flip) {}};class Dinic {private:    bool b[Maxn];    int a[Maxn];    unsigned p[Maxn], cur[Maxn], d[Maxn];public:    vector<Edge> G[Maxn];    unsigned s, t;    void Init(unsigned n) {        for (int i = 0; i <= n; ++i)            G[i].clear();    }    void AddEdge(unsigned u, unsigned v, int c) {        G[u].push_back(Edge(v, c, 0, G[v].size()));        G[v].push_back(Edge(u, 0, 0, G[u].size() - 1)); //使用无向图时将0改为c即可     }    bool BFS() {        unsigned u, v;        queue<unsigned> q;        memset(b, 0, sizeof(b));        q.push(s);        d[s] = 0;        b[s] = 1;        while (!q.empty()) {            u = q.front();            q.pop();            for (auto it = G[u].begin(); it != G[u].end(); ++it) {                Edge &e = *it;                if (!b[e.v] && e.c>e.f) {                    b[e.v] = 1;                    d[e.v] = d[u] + 1;                    q.push(e.v);                }            }        }        return b[t];    }    int DFS(unsigned u, int a) {        if (u == t || a == 0)            return a;        int flow = 0, f;        for (unsigned &i = cur[u]; i<G[u].size(); ++i) {            Edge &e = G[u][i];            if (d[u] + 1 == d[e.v] && (f = DFS(e.v, min(a, e.c - e.f)))>0) {                a -= f;                e.f += f;                G[e.v][e.flip].f -= f;                flow += f;                if (!a) break;            }        }        return flow;    }    int MaxFlow(unsigned s, unsigned t) {        int flow = 0;        this->s = s;        this->t = t;        while (BFS()) {            memset(cur, 0, sizeof(cur));            flow += DFS(s, INF);        }        return flow;    }};void Input(Dinic &d) {    memset(Dif, 0, sizeof(Dif));    int u, v, b;    char c;    for (int i = 1; i <= M; ++i) {        QIn(u);        QIn(v);        QIn(b);        d.AddEdge(u, v, INF); //由于无上界,直接写INF好了,反正流量不可能达到INF-b        Dif[u] -= b;        Dif[v] += b;    }}int main() {    while (~scanf("%d %d",&N,&M) && M) { //N可以等于0!        S = N + 1, T = N + 2;        SS = S + 2, ST = T + 2;        Dinic D;        Input(D);        int sum = 0;        for (int i = 1; i <= T; ++i) { //建立与超级源汇点ss、st的边(别漏了源汇点!)            if (Dif[i] > 0) {                D.AddEdge(SS, i, Dif[i]);                sum += Dif[i];            }            if (Dif[i] < 0) D.AddEdge(i, ST, -Dif[i]);        }        int ans=D.MaxFlow(SS, ST);        D.AddEdge(T, S, INF);        ans += D.MaxFlow(SS, ST);        if (ans != sum) {            puts("impossible");        }        else {            printf("%d\n", D.G[T].rbegin()->f);        }    }    return 0;}
原创粉丝点击