Edmonds-Karp算法,最大流POJ(1459)

题目链接:http://poj.org/problem?id=1459

解题报告:

电力调度站不涉及流的产生和消耗,不用考虑,Edmonds-Karp算法,就是利用剩余网络和增广路来解决,网络中的最大流。

原理:剩余网络,就是一种回退,构造完在剩余网络后,在剩余网络中找一条增广路,其中的最小流量,每个边加上这个最小流量或者减去这个最小流量,那么流就变成最大的了。

在加上或者减去这个最小流量时,初始化flow[][]这个剩余网络为0,最小流量node[v]=min(node[u],cap[u][v]-flow[u][v]),重新更新flow[][]+=node[t]后,就是真正的剩余网络了,cap[u][v]-flow[u][v]就表示的是这条边最大的流量了,这里也可以看出初始化flow[][]为0的目的了。

然后是,增广路的搜索,BFS广度优先搜索出每一条增广路,没找到一条增广路,就更新flow剩余网络,直到不存在增广路,就是说,直到原网络没有了任何的可以加上的流了。

这个题目,不能直接用传统意义上的最大流,因为这么没有一个绝对的源点和汇点,所以要建一个超级源点s,和超级汇点,n,n+1;

#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
#define MAX 120

using namespace std;

int n;                          ///节点数
int np;                         ///发电站数
int nc;                         ///消费者数
int m;                          ///传输线数
int cap[MAX][MAX];              ///网络的邻接矩阵

int from,to,value;


///形参s是超级源点,形参t是超级汇点
int EKarp(int s,int t) {
    queue<int> Q;               ///用于BFS的搜索队列
    int flow[MAX][MAX];         ///剩余网络的邻接矩阵
    int pre[MAX];               ///增广路径
    int node[MAX];              ///增广路径上的最小流
    int u,v;
    int maxflow=0;              ///网络的最大流
    ///剩余网络的初始化
    memset(flow,0,sizeof(flow));

    ///不断寻找增广路径
    while(true) {
        Q.push(s);
        memset(node,0,sizeof(node));
        node[s]=100000;         ///最小流量初值,无穷大

        ///BFS算法,搜索增广路径
        while(!Q.empty()) {
            u=Q.front();
            Q.pop();

            for(v=0; v<=t; v++) {
                if(!node[v]&&cap[u][v]>flow[u][v]) {
                    Q.push(v);
                    node[v]=min(node[u],cap[u][v]-flow[u][v]);
                    pre[v]=u;
                }
            }
        }

        ///当瓶颈容量为0时,说明不存在增广路径,搜索结束
        if(node[t]==0) break;
        ///根据增广路径和瓶颈容量,更新剩余网络
        for(u=t; u!=s; u=pre[u]) {
            flow[pre[u]][u]+=node[t];
            flow[u][pre[u]]-=node[t];
        }

        maxflow+=node[t];
    }
    return maxflow;     ///总流量累加
}


int main() {
    while(scanf("%d%d%d%d",&n,&np,&nc,&m)!=EOF) {
        memset(cap,0,sizeof(cap));

        ///读取输电线的数据
        while(m--) {
            scanf(" (%d,%d)%d",&from,&to,&value);
            cap[from][to]=value;
        }

        ///读取发电站数据,构造超级源点
        while(np--) {
            scanf(" (%d)%d",&from,&value);
            cap[n][from]=value;
        }

        ///读取消费者数据,构造超级汇点
        while(nc--) {
            scanf(" (%d)%d",&from,&value);
            cap[from][n+1]=value;
        }

        printf("%d
",EKarp(n,n+1));
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/TreeDream/p/5506511.html