POJ - 1273 Dinic 算法模板

題目:POJ—1273
題意: 給你m個點 n 條邊 , 構圖後。求最大流
算法: EK算法 或者dinic算法都可以, dinic算法是EK算法的優化, 可能有一種圖:這裏寫圖片描述
在這個圖中Ek算法可能會反覆走1 -> 2 -> 3 -> 4 這條路, 一直走到1 -> 2 的流量完爲止
而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);
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章