Dinic 算法模板

/* 反复BFS的原因是因为每一次的DFS后,整个图的流量会发生改变,所以需要重复构层次图*/

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<string>
#define Min(a,b) a<b?a:b
#define Max(a,b) a>b?a:b
#define CL(a,num) memset(a,num,sizeof(a));
#define eps  1e-12
#define inf   0x7fffffff

//freopen("data.txt","r",stdin);
/*
dinic算法模板
复杂度O(n*m*m)
该模板为邻接矩阵模板
题目: POJ1273
该算法相当于Ek算法的优化
构建分层图后,dfs过程不会反复的往回走
*/
const double pi  = acos(-1.0);
typedef   __int64  ll;
const int maxn = 300 ;
using namespace std;
int n , m;
int flow[maxn][maxn],dis[maxn] ;//dis[i],表示  到 原点  s 的 层数

int bfs()// 重新 建 图 (按 层数 建图)
{
    CL(dis,-1);
    dis[1] = 0 ;
    queue<int>que;
    que.push(1);
    while(!que.empty())
    {
        int  k = que.front();que.pop() ;
        for( int i = 1;i<= n;i++)
        {
            if(flow[k][i] > 0 && dis[i] < 0 )// 如果 可以  可以到达 但 还没有 访问
            {
                dis[i] = dis[k]+ 1 ;
                que.push(i) ;
            }
        }
    }

    if(dis[n] > 0) return 1;
    else return  0 ;

}
int  dfs(int x,int mx)// 查找  路径上的 最小 的 流量
{

    int i , a ;
    if(x == n) return mx ; // 如果搜索到了N点(终点) 就可以回溯了

    for(i = 1;i<= n;i++)
    {
        if(flow[x][i] > 0 && dis[i] == dis[x] + 1  && (a =dfs(i,min(mx,flow[x][i]))) ) // 这里的 a 为一条曾广路经的最小流
        {
            flow[x][i] -= a;
            flow[i][x] += a;
            return a ;
        }
    }
    return 0 ;
}
int main()
{
    //freopen("data.txt","r",stdin);
    int i ,s,e,c;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        CL(flow,0); /// 初始化函数
        for(i = 0  ; i < m;i++)
        {
            scanf("%d%d%d",&s,&e,&c);
            flow[s][e] += c;   ///邻接矩阵构图
        }
      int ans = 0;
      int res;

      while(bfs())
      {
         while(res = dfs(1,inf)) ans+= res ;
      }
      printf("%d\n",ans);
    }

}

猜你喜欢

转载自blog.csdn.net/qq_42894605/article/details/81945219