POJ-1459 Power Network 网络流

  题中给出了各种点的定义,其实我们只要建立两个虚拟节点就可以了。一个是源点流到所有的p点,一个是汇点,所有的c点流过去,再求最大流就可以了。当然题中的输入数据比较恶心,这里用了字符串的处理方式来解决。

  代码如下:

#include <cstring>

#include <cstdlib>

#include <cstdio>

#include <algorithm>

#include <queue>

#define S N

#define T (N+1)

#define INF 0x3fffffff

#define MAXN 105

using namespace std;



int N, np, nc, M, flow[MAXN][MAXN], cap[MAXN][MAXN];

int c[MAXN], p[MAXN], Maxflow;



void getint(int &t)

{

    char c;

    while (c = getchar(), c < '0' || c > '9') {};

    t = c - '0';

    while (c = getchar(), c >= '0' && c <= '9') {

        t = t * 10 + c - '0';

    }

}



void bfs()

{

    bool finish = false;

    int pos;

    while (!finish) {

        memset(c, 0, sizeof (c));

        c[S] = INF;  // 虚拟出一个无穷的流从源点流出来

        queue<int>q;

        q.push(S);

        while (!q.empty()) {

            if (c[T]) {

                break;

            }

            pos = q.front();

            q.pop();

            for (int i = 0; i <= N+1; ++i) {

                if (!c[i] && flow[pos][i] < cap[pos][i]) {

                // 前面这个!c[i]很重要,它表示本轮中推送过流量的点不能作为二次推流的节点

                    c[i] = min(cap[pos][i]-flow[pos][i], c[pos]); // 这个值一定是大于零的

                    p[i] = pos;  // 记录路径,以便后面的更新

                    q.push(i);

                }

            }

        }

        if (c[T] == 0) {  // 本次寻找增广路径失败

            finish = true;

        }

        else {

            Maxflow += c[T];  // 流入到汇点的新流量

            pos = T;

            while (pos != S) {  // 没有回溯到源点

                flow[p[pos]][pos] += c[T];

                flow[pos][p[pos]] -= c[T];

                pos = p[pos];

            }

        }

    }

}



int main()

{

    char s[15];

    int x, y, z; // 从0号节点开始,我们可以设置一个N号节点,并建立c到N节点的流量无上限的边

    while (scanf("%d %d %d %d", &N, &np, &nc, &M) == 4) {

        memset(cap, 0, sizeof (cap));

        memset(flow, 0, sizeof (flow));

        Maxflow = 0;

        for (int i = 0; i < M; ++i) {

            getint(x), getint(y), getint(z);

        //    printf("%d %d %d\n", x, y, z);

            cap[x][y] = z;  // 建立边的容量

        }

        for (int i = 0; i < np; ++i) {

            getint(x), getint(y);

            cap[N][x] = y;  // 创建源点

        }

        for (int i = 0; i < nc; ++i) {

            getint(x), getint(y);

            cap[x][N+1] = y;  // 创建汇点

        }

        bfs();

        printf("%d\n", Maxflow);

    }

    return 0;

}

你可能感兴趣的:(NetWork)