Ford-Fulkerson【一般增广 路算法】

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
const int maxn=1005;
int n,m;
struct ArcType{//弧结构 
	int c,f;//容量、流量 
}; 
ArcType edge[maxn][maxn];//邻接矩阵、每个元素为ArcType类型 
int flag[maxn];//顶点状态:-1--未标号、0-已标号未检查、1-已标号已检查 
int pre[maxn];//标号的第一个分量、指明标号从哪个顶点得到,以便找出可改进量 
int alpha[maxn];//标号的第二个分量:可改进两
int que[maxn];
int v;
int qs,qe;//队列头位置、尾位置
void ford() {
	while(1){//标号直至不存在可改进路 
		memset(flag,-1,sizeof flag) ;
		memset(pre,-1,sizeof pre);
		memset(alpha,-1,sizeof alpha);
		flag[0]=0,pre[0]=0,alpha[0]=INF;
		qs=qe=0;
		que[qe]=0;
		qe++;
		//qs<qe表示队列非空、flag[n-1]==-1表示汇点未标号 
		while(qs<qe&&flag[n-1]==-1) {
			v=que[qs];
			qs++;//取出队列头结点 
			for(int 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;
						pre[i]=v;//给顶点i标号、(已标号未检查) 
						alpha[i]=min(alpha[v],edge[v][i].c-edge[v][i].f);
						que[qe++] =i;//顶点i入队列 
					}
					else if(edge[i][v].c<INF&&edge[i][v].f>0) {//反向且有流量 
						flag[i]=0;
						pre[i]=-v;//给顶点i标号、(已标号未检查)
						alpha[i]=min(alpha[v],edge[i][v].f);
						que[qe++]=i;
					}
				}
			}
			flag[v]=1;
		}
		//当汇点没有获得标号或者汇点的调整量为0,应该退出while循环 
		if(flag[n-1]==-1||alpha[n-1]==0) break;
		//当汇点有标号时、进行调整
		int k1=n-1,k2=abs(pre[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;//调整一直到源点v0
			k1=k2;
			k2=abs(pre[k1]) ;
		}
	}
	int maxflow=0;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(i==0&&edge[i][j].f<INF)
				maxflow+=edge[i][j].f;//源点的流出量、即最大流 
		}
	}
	printf("%d\n",maxflow);
}
int main(){
	int u,v,c,f;
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			edge[i][j].c=edge[i][j].f=INF;
		}
	}
	for(int i=0;i<m;i++){
		scanf("%d%d%d%d",&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
*/

猜你喜欢

转载自blog.csdn.net/qq_37867156/article/details/81390070
今日推荐