有上下界的网络流

#include <iostream>
#include <cstring>
#include<cstdlib>

using namespace std;

const int INF1 = 100000000;
const int INF2 = 10000;
const int MAXN = 20;

struct Arctype
{
    int b, c, f;
};

Arctype Edge[MAXN][MAXN];
Arctype AccEdge[MAXN][MAXN];

int n, m;

int MIN(int a, int b)
{
    return a < b ? a : b;
}

int fabs(int a)
{
    return a < 0 ? (-a) : a;
}


void Ford(Arctype NetWork[][MAXN], int s, int t, int num)
{
    int pre[MAXN];
    int flag[MAXN];
    int alpha[MAXN];
    int Q[MAXN];
    int qs, qe;
    while(1)
    {
        memset(pre, 0xff, sizeof(pre));
        memset(alpha, 0, sizeof(alpha));
        memset(flag, 0xff, sizeof(flag));
        flag[s] = 0, alpha[s] = INF1, pre[s] = 0;
        qs = qe = 0;
        Q[qe++] = s;
        while(qs < qe && flag[t] == -1)
        {
            int u = Q[qs++];
            for(int v = 0; v <= t; ++v)
            {
                if(flag[v] == -1)
                {
                    if(NetWork[u][v].c < INF1 && NetWork[u][v].f < NetWork[u][v].c)
                    {
                        flag[v] = 0;
                        pre[v] = u;
                        alpha[v] = MIN(alpha[u], NetWork[u][v].c - NetWork[u][v].f);
                        Q[qe++] = v;
                    }
                    else if(NetWork[v][u].c < INF1 && NetWork[v][u].f > NetWork[v][u].b)
                    {
                        flag[v] = 0;
                        pre[v] = -u;
                        alpha[v] = MIN(alpha[u], NetWork[v][u].f - NetWork[v][u].b);
                        Q[qe++] = v;
                    }
                }
            }
            flag[u] = 1;
        }


        if(flag[t] == -1 || alpha[t] == 0)
            break;
        int k1 = t;
        int k2 = fabs( pre[k1] );
        int a = alpha[k1];
        while(1)
        {
            if(NetWork[k2][k1].f < INF1)
                NetWork[k2][k1].f += a;
            else
                NetWork[k1][k2].f -= a;
            if(k2 == s)
                break;
            k1 = k2;
            k2 = fabs( pre[k1] );
        }
    }

    int MaxFlow = 0;
    for(int i = s; i <= t; ++i)
    {
        for(int j = s; j <= t; ++j)
        {
            if(i == s && NetWork[i][j].f < INF1)
                MaxFlow += NetWork[i][j].f;
            if(i == s && NetWork[j][i].f < INF1)
                MaxFlow -= NetWork[j][i].f;
            if(NetWork[i][j].c < INF1 && NetWork[i][j].f < INF1)
                cout<<i<<" -> "<<j<<": "<<NetWork[i][j].f<<endl;
        }
    }
    if(num == 1)
        cout<<"MaxFlow : "<<MaxFlow<<endl;
    else if(num == 0)
        cout<<"MinFlow : "<<MaxFlow<<endl;
}


int ReadCase()
{
    int u, v, b, c;
    cin>>n>>m;
    if(n == 0 && m == 0)
        return 0;
    for(int i = 0; i < MAXN+2; ++i)
    {
        for(int j = 0; j < MAXN+2; ++j)
        {
            Edge[i][j].b = Edge[i][j].c = Edge[i][j].f = INF1;
        }
    }
    for(int i = 1; i <= m; ++i)
    {
        cin>>u>>v>>b>>c;
        Edge[u][v].b = b;
        Edge[u][v].c = c;
        Edge[u][v].f = 0;
    }
    return 1;
}

int Accompany()
{
    memcpy(AccEdge, Edge, sizeof(Edge));
    int i, j;
    int sum1, sum2;
    for(i = 1; i <= n; ++i)//
    {
        sum1 = sum2 = 0;
        for(j = 0; j <= n; ++j)
        {
            if(AccEdge[i][j].b < INF1)
                sum1 += AccEdge[i][j].b;
            if(AccEdge[j][i].b < INF1)
                sum2 += AccEdge[j][i].b;
        }
        AccEdge[0][i].c = sum2, AccEdge[0][i].b = AccEdge[0][i].f = 0;
        AccEdge[i][n+1].c = sum1, AccEdge[i][n+1].b = AccEdge[i][n+1].f = 0;
    }

    for(i = 1; i <= n; ++i)
    {
        for(j = 1; j <= n; ++j)
        {
            if(AccEdge[i][j].c < INF1)
            {
                AccEdge[i][j].c -= AccEdge[i][j].b;
                AccEdge[i][j].b = 0;
            }
        }
    }
    AccEdge[1][n].c = AccEdge[n][1].c = INF2;
    AccEdge[1][n].b = AccEdge[1][n].f = 0;
    AccEdge[n][1].b = AccEdge[n][1].f = 0;

    Ford(AccEdge, 0, n+1, -1);

    bool flag = true;
    for(i = 1; i <= n; ++i)
        if(AccEdge[0][i].c < INF1 && AccEdge[0][i].f != AccEdge[0][i].c)
            flag = false;
    if(!flag)
    {
        cout<<"No feasible network flow !"<<endl;
        return 0;
    }



    for(i = 1; i <= n; ++i)
    {
        for(j = 1; j <= n; ++j)
        {
            if(Edge[i][j].c < INF1)
                Edge[i][j].f = Edge[i][j].b + AccEdge[i][j].f;
        }
    }

    Ford(Edge, 1, n, 1);


/**
    int b, c, f;

    for(i = 1; i <= n; ++i)
    {
        for(j = 1; j <= n; ++j)
            if(Edge[i][j].c < INF1)
                Edge[i][j].f = AccEdge[i][j].f + Edge[i][j].b;
    }


    for(int i = 1; i <= n; ++i)
    {
        b = Edge[1][i].b, c = Edge[1][i].c, f = Edge[1][i].f;
        Edge[1][i].b = Edge[n][i].b, Edge[1][i].c = Edge[n][i].c, Edge[1][i].f = Edge[n][i].f;
        Edge[n][i].b = b, Edge[n][i].c = c, Edge[n][i].f = f;

        b = Edge[i][1].b, c = Edge[i][1].c, f = Edge[i][1].f;
        Edge[i][1].b = Edge[i][n].b, Edge[i][1].c = Edge[i][n].c, Edge[i][1].f = Edge[i][n].f;
        Edge[i][n].b = b, Edge[i][n].c = c, Edge[i][n].f = f;
    }


    Ford(Edge, 1, n, 0);
*/
    return 1;
}

int main()
{
    while(ReadCase())
        Accompany();
    return 0;
}


/**

6 8
1 2 0 10
1 3 1 3
2 4 2 8
3 5 5 7
4 3 2 4
4 6 2 6
5 2 1 3
5 6 3 5


*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值