一般增广路方法求网络最大流(Ford-Fulkerson算法)

/*

Time:2015-6-18

接触网络流好几天了

写的第一个模版————Ford-Fulkerson算法

作用:求解网络最大流

注意:源点是0 汇点是1  如果题目输入的是1到n  请预处理减1

*/

#include<cstdio>

#include<cstring>

#include<cmath>

#include<queue>

#include<algorithm>

using namespace std;



const int INF = 0x7fffffff;//无穷大

const int maxn = 1000 + 10;//这里可以设置结点的数量

int n, m;

int flag[maxn], pre[maxn], alpha[maxn];

int c[maxn][maxn], f[maxn][maxn];

queue<int>Q;



int main()

{

    int i, j, u, v, cc, ff;

    scanf("%d%d", &n, &m);

    for (i = 0; i<n; i++) for (j = 0; j<n; j++) c[i][j] = INF, f[i][j] = INF; //初始化不存在弧

    for (i = 0; i<m; i++)

    {

        scanf("%d%d%d%d", &u, &v, &cc, &ff);//输入弧的起点,弧的终点,弧的容量,弧的流量

        

        //解决重边问题

        if (c[u][v] == INF) { c[u][v] = cc; f[u][v] = ff; }

        else { c[u][v] += cc; f[u][v] += ff; }

    }

    //0是源点 n-1汇点

    int startt, endd;

    startt = 0;

    endd = n - 1;

    while (1)

    {

        while (!Q.empty()) Q.pop();

        memset(flag, -1, sizeof(flag));

        memset(pre, -1, sizeof(pre));

        memset(alpha, -1, sizeof(alpha));

        flag[startt] = 0;//源点已标号 但是未检查邻接顶点

        pre[startt] = 0;//源点从自己推过来

        alpha[startt] = INF;//源点可以发出INF的流量

        Q.push(startt);

        while ((!Q.empty()) && flag[endd] == -1)

        {

            int h = Q.front(); Q.pop();

            for (i = 0; i<n; i++)

            {

                //前向弧

                if (c[h][i] != INF)//有路

                {

                    if (f[h][i]<c[h][i])//不饱和

                    {

                        if (flag[i] == -1)//i顶点未标号

                        {

                            flag[i] = 0;//i顶点已标号 但是未检查邻接顶点

                            pre[i] = h;//i从h推过来

                            //alpha[i]取决于alpha[h]与c[h][i]-f[h][i]的较小值

                            if (c[h][i] - f[h][i] <= alpha[h]) alpha[i] = c[h][i] - f[h][i];

                            else alpha[i] = alpha[h];

                            Q.push(i);//i顶点进入队列 等待检查邻接顶点

                        }

                    }

                }

                //后向弧

                if (c[i][h] != INF)//有路

                {

                    if (f[i][h]>0)//非零流弧

                    {

                        if (flag[i] == -1)//i顶点未标号

                        {

                            flag[i] = 0;//i顶点已标号 但是未检查邻接顶点

                            pre[i] = -h;//i从h推过来 标号为- 意思是后向弧

                            //alpha[i]取决于alpha[h]与f[i][h]的较小值

                            if (alpha[h] <= f[i][h]) alpha[i] = alpha[h];

                            else alpha[i] = f[i][h];

                            Q.push(i);//i顶点进入队列 等待检查邻接顶点

                        }

                    }

                }

            }

            flag[h] = 1;//h顶点已标号,并且已经检查所有的邻接顶点

        }

        if (flag[endd] == -1 || alpha[endd] == 0) break; //已经不存在增广路,不再寻找

        int a = alpha[endd];//可改进量

        int now = endd;

        while (1)

        {

            if (now == 0) break;

            if (pre[now] >= 0)

            {

                f[pre[now]][now] += a;

                now = pre[now];

            }

            else if (pre[now]<0)

            {

                f[now][-pre[now]] -= a;

                now = -pre[now];

            }

        }



    }

    for (i = 0; i<n; i++)

    for (j = 0; j<n; j++)

    if (f[i][j] != INF)

        printf("%d --> %d : %d\n", i, j, f[i][j]);

    int maxflow = 0;

    for (i = 0; i<n; i++) if (f[0][i] != INF)  maxflow += f[0][i];

    printf("maxflow = %d\n", maxflow);

    return 0;

}

 

你可能感兴趣的:(for)