最大流算法_最短增广算法

/*
网络流最短增广路算法
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cmath>
#define oo 0x3f3f3f3f
using namespace std;
const int maxn = 1010;
struct node
{
    int c,f;
};
int n,m;
node mp[maxn][maxn];
int level[maxn];
int last[maxn][maxn];
int que[maxn*1000],qs,qe;
int vis[maxn], par[maxn],add[maxn];
void BuildRemain(int s, int t)//构造剩余网络
{
    memset(level, -1, sizeof(level));
    memset(last, oo, sizeof(last));
    for(int i = 1; i<= n; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            if(mp[i][j].c!=oo)
            {
                if(mp[i][j].c-mp[i][j].f>0)
                    last[i][j] = mp[i][j].c-mp[i][j].f;
                if(mp[i][j].f>0)
                last[j][i] = mp[i][j].f;
            }
        }
    }
    qs = qe = 0;
    que[qs++] = s;
    level[s] = 0;
    while(qe<qs)//标号分层是对残余网络
    {
        int u = que[qe++];
        for(int i = 1; i <= n; i++)
        {
            if(level[i]==-1&&last[u][i]!=oo)
            {
                level[i] = level[u]+1;
                que[qs++] = i;
            }
        }
    }
}
int FindBfs(int s, int t)
{
    memset(vis, 0,sizeof(vis));
    memset(par, 0,sizeof(par));
    memset(add, 0,sizeof(add));
    vis[s] = 1;
    par[s] = 0;
    add[s] = oo;
    qs = qe = 0;
    que[qs++] = s;
    while(qe<qs&&!vis[t])
    {
        int u = que[qe++];
        for(int i = 1; i <= n; i++)
        {
            if(!vis[i]&&last[u][i]!=oo&&level[i]==level[u]+1)
            {
                vis[i] = 1;
                par[i] = u;
                add[i] = min(add[u], last[u][i]);
                que[qs++] = i;
            }
        }
    }

    if(!vis[t]||add[t]==0)return 0;
    return 1;
}
void Zdzgl(int s,int t)
{
    int flag = 0;
    while(1)
    {
        /*(1)构造残留网络*/
        BuildRemain(s,t);
        /*(2)构造层次网络,寻找增广路*/
        flag = 0;
        while(FindBfs(s,t))
        {
            flag = 1;
            int u = par[t],v=t;
            int a = add[t];
            while(u!=0)
            {
                if(mp[u][v].c!=oo)
                    mp[u][v].f += a;
                else
                    mp[v][u].f -= a;
                last[u][v]-=a;
                if(last[u][v]==0)last[u][v] = oo;
                v = u;
                u = par[v];
            }
        }

        if(!flag)break;
    }
    int Maxflow = 0;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= n; j++)
        {
            if(i == 1 && mp[i][j].f!=oo)
                Maxflow += mp[i][j].f;
            if(mp[i][j].f != oo)
                printf("%d-->%d: %d\n",i,j,mp[i][j].f);
        }
    }
    printf("MaxFlow:%d\n",Maxflow);
}
int main()
{
    int u,v,c,f;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                mp[i][j].c = mp[i][j].f = oo;
            }
        }

        for(int i = 0; i < m; i++)
        {
            scanf("%d%d%d%d",&u,&v,&c,&f);
            mp[u][v].c = c;
            mp[u][v].f = f;
        }

        Zdzgl(1,n);
    }
    return 0;
}
/*
7  12
1 2 4 3
1 3 10 3
2 3 1 1
2 5 7 2
2 4 2 0
3 4 5 1
3 6 3 3
4 5 6 0
4 6 1 1
5 7 9 2
6 5 5 0
6 7 6 4
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值