网络流-Dinic

http://comzyh.com/blog/archives/568/

http://blog.csdn.net/pi9nc/article/details/23339111

http://wenku.baidu.com/link?url=QcjoxjvmNIGIyvaRRYN5_Jimdj0fI1F3-y1XfjkHBON9c6_eNUbfpDXKRjwGuztLwYvhobWVRDWkEclaq1iu24m2CJVVHH60iQBACHdcTVm

还可以看看我在宁波工程学院集训队PPT的基础上修改的网络流PPT

论文:国家集训队2007论文集里的王欣上《浅谈基于分层思想的网络流算法》也很好。

反向边:从层次图中第 i 层给返回到 i - 1层的路;

增广:从层次图里的第一层到第二层,再继续到汇点,然后根据递归性质返回到增广前原路中源点能到达的最远点,继续从这个点的其他边找路。


层次图:按照【从源点到该点的最短距离】分层的图,如

Dinic算法步骤:
    1、根据残存网络计算层次图。若源点不能与汇点联通,则算法结束
    2、在层次图中使用DFS进行增广直到不存在增广路
    3、转步骤1直至源汇点不通


#include <string.h>
#include <iostream>
#include <cstdio>
using namespace std;
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define FOR( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define CLR( a , x ) memset ( a , x , sizeof (a) );
#define RE freopen("1.in","r",stdin);
#define WE freopen("output.txt","w",stdout);
#define debug(x) cout<<#x<<":"<<(x)<<endl;
const int maxn=205;
int tab[maxn][maxn],dis[maxn],n,m;  //tab为流量,dis为层次
//bfs找层次图
int bfs(int s,int t)
{
    int q[maxn],head=0,tail=0;
    q[tail++]=s;
    memset(dis,-1,sizeof(dis));
    dis[s]=0;
    while(head<tail)
    {
        int cur=q[head++];
        for(int i=1;i<=n;i++)
        {
            if(dis[i]<0&&tab[cur][i]>0)
            {
                dis[i]=dis[cur]+1;
                q[tail++]=i;
            }
        }
    }
    if(dis[t]>0)    return 1;
    return 0;   //dis[t]=-1:路不通
}
//dfs为一次增广,s->t
int dfs(int s,int t,int low)//Low为增广路径上的最小流量
{
    int flow=0;
    if(s==t)    return low; //到汇点直接返回目前为止的最小流量
    for(int i=1;i<=n;i++)
    {       //在下一层里找
        if(tab[s][i]>0
           &&dis[i]==dis[s]+1
           &&(flow=dfs(i,t,min(low,tab[s][i]))))
        {
            tab[s][i]-=flow;    //不断的减流量
            tab[i][s]+=flow;
            return flow;        //能到汇点
        }
    }
    return 0;
}

int main() {
//    RE
    int a,b,c;
    while(cin>>m>>n)
    {
        CLR(tab,0); //流量初始化为0
        while(m--)
        {
            cin>>a>>b>>c;
            tab[a][b]+=c;   //重边
        }
        int ans=0,tans=0;
        while(bfs(1,n))         //直到源点不能到汇点为止
            while(tans=dfs(1,n,0x7FFFFFFF))     //在同一个层次图里尽量找增广路
                ans+=tans;
        cout<<ans<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值