題目: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);
}
}