Ford-Fulkerson 標號法求網路最大流
使用Ford-Fulkerson 標號法求網路最大流。
①c、f初始化為INF表示該邊不存在
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <iomanip>
#include <algorithm>
#define maxn 10010
#define INF 0xfffffff
using namespace std;
struct ArcType
{
int c,f;//容量、流量
};
ArcType edge[maxn][maxn];
int n,m;//頂點數、弧數
int flag[maxn];//頂點狀態:-1——未標號;0——已標號未檢查;1——已標號已檢查
int prev[maxn];//標號的第一個分量:指明標號從哪個頂點而來,以便找出可改進量
int alpha[maxn];//標號的第二個分量:可改進量α
int que[maxn];//相當於BFS中的佇列
int v;//佇列頭元素
int qs,qe;//隊首隊尾的位置
int i,j;
void ford()//標號法求網路最大流
{
while(1)//標號,直到不存在可改進路
{
memset(flag,-1,sizeof(flag));
memset(prev,-1,sizeof(prev));
memset(alpha,-1,sizeof(alpha));
flag[0]=0;
prev[0]=0;
alpha[0]=INF;
qs=qe=0;
que[qe]=0;//源點0入佇列
++qe;
while(qs<qe&&flag[n-1]==-1)
{
v=que[qs];//取隊首元素
++qs;
for(i=0; i<n; ++i)//檢查頂點v的正向和反向鄰接點
if(flag[i]==-1)
{
if(edge[v][i].c<INF&&edge[v][i].f<edge[v][i].c)//正向且未滿
{
flag[i]=0;//給頂點i標號,但此時未檢查
prev[i]=v;
alpha[i]=min(alpha[v],edge[v][i].c-edge[v][i].f);
que[qe]=i;//頂點i入隊
++qe;
}
else if(edge[i][v].c<INF&&edge[i][v].f>0)//反向且有流量
{
flag[i]=0;
prev[i]=-v;
alpha[i]=min(alpha[v],edge[i][v].f);
que[qe]=i;
++qe;
}
}
flag[v]=1;//標記頂點i已經檢查
}
if(flag[n-1]==-1||alpha[n-1]==0) break;//匯點無標號或匯點的調整量為0
int k1=n-1,k2=abs(prev[k1]);
int a=alpha[n-1];//可改進量α
while(1)
{
if(edge[k2][k1].f<INF) edge[k2][k1].f+=a;//正向
else edge[k1][k2].f-=a;//反向
if(k2==0) break;//一直調整到源點0
k1=k2;
k2=abs(prev[k2]);
}
}
int maxflow=0;//最大流量
for(i=0; i<n; ++i)
for(j=0; j<n; ++j)
{
if(i==0&&edge[i][j].f<INF) maxflow+=edge[i][j].f;
if(edge[i][j].f<INF) cout<<i<<"->"<<j<<":"<<edge[i][j].f<<endl;
}
cout<<"maxflow:"<<maxflow<<endl;
}
int main()
{
int u,v,c,f;//弧的起點終點容量流量
cin>>n>>m;//頂點個數、弧數
for(i=0; i<n; ++i)
for(j=0; j<n; ++j)
edge[i][j].c=edge[i][j].f=INF;//初始化,INF表示無邊相連
for(i=0; i<m; ++i)
{
cin>>u>>v>>c>>f;
edge[u][v].c=c;//構造鄰接矩陣
edge[u][v].f=f;
}
ford();
return 0;
}
/*
6 10
0 1 8 2
0 2 4 3
1 3 2 2
1 4 2 2
2 1 4 2
2 3 1 1
2 4 4 0
3 4 6 0
3 5 9 3
4 5 7 2
*/
②未初始化
void ford()//標號法求網路最大流
{
int flow[maxn][maxn];//節點之間的流量Fij
int prev[maxn];//可改進路徑上前一個節點的標號,相當於標號的第一個分量
int minflow[maxn];//每個頂點的可改進量α,相當於標號的第二個分量
int que[maxn];
int qs,qe;//佇列首尾位置座標
int v,p;//當前頂點、儲存Cij-Fij
for(i=0; i<maxn; ++i)
for(j=0; j<maxn; ++j)
flow[i][j]=0;
minflow[0]=INF;//源點標號的第二分量為無窮大
while(1)//標號法
{
for(i=0; i<maxn; ++i)//每次標號前,每個頂點重新回到未標號狀態
prev[i]=-2;
prev[0]=-1;
qs=0;
que[qs]=0;//源點入隊
qe=1;
while(qs<qe&&prev[t]==-2)
{
v=que[qs];//取佇列頭節點
++qs;
for(i=0; i<t+1; ++i)//prev[i]==-2表示頂點i未標號
if(prev[i]==-2&&(p=edge[v][i].c-flow[v][i]))//edge[v][i].c-flow[v][i]!=0能保證i是v鄰接頂點且能進行標號
{
prev[i]=v;
que[qe]=i;
++qe;
minflow[i]=(minflow[v]<p)?minflow[v]:p;
}
}
if(prev[t]==-2) break;//匯點t無標號,標號法結束
for(i=prev[t],j=t; i!=-1; j=i,i=prev[i])//調整過程
{
flow[i][j]+=minflow[t];
flow[j][i]=-flow[i][j];
}
}
for(i=0,p=0; i<t; ++i)//統計進入匯點的流量即最大流的流量
p+=flow[i][t];
cout<<p<<endl;
}
相關文章
- POJ 1149-PIGS(Ford-Fulkerson 標號法求網路最大流)
- 網路流最大流
- EK求最大流
- 淺談網路最大流
- hdu 4292 網路最大流
- 【模板】網路流最大流
- 網路最大流演算法演算法
- 網路流(最大流,最小割)
- Dinic/ISAP求最大流
- 網路中最小費用最大流
- 網路最大流 Dinic演算法演算法
- 網路---無法訪問目標主機和請求超時的區別
- 【網路流】有源匯上下界最大流
- poj1087 網路最大流
- 最嚴網路資訊稽核標準!11種內容涉嫌違法,你“中招”了嗎?
- 【計算機網路常見面試題】利用IP地址和子網掩碼求網路號和主機號計算機網路面試題
- 多個網路請求中GCD訊號量的使用GC
- Android網路請求(終) 網路請求框架RetrofitAndroid框架
- Android網路請求(3) 網路請求框架OkHttpAndroid框架HTTP
- 網路流最大流、最小割學習筆記筆記
- Android網路請求(4) 網路請求框架VolleyAndroid框架
- volley建立標準的網路請求(Making a Standard Request)
- 網路請求了
- [網路流24題] 魔術球問題 (最大流)
- 美國網際網路大流量網站和社交網路一天資料分佈圖網站
- SQLServer最大流水號的解決方法SQLServer
- 攜號轉網,使用者最關心的還是網路質量薦
- POJ1273 Drainage Ditches【網路流 最大流】AI
- HTTP網路請求原理HTTP
- iOS原生網路請求iOS
- 網路請求圖片
- 網路請求LCNetwork
- 網路資料請求
- 47.4mAP!最強Anchor-free目標檢測網路:SAPD
- 網路號、主機號、子網號、子網掩碼、子網劃分
- 網路請求優化之取消請求優化
- 研究顯示聯合國網際網路接入目標無法如期實現
- 無線網路有感嘆號受限制無法上網怎麼回事?