测试数据
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
0->1:4
0->2:4
1->3:2
1->4:2
2->1:0
2->3:1
2->4:3
3->4:0
3->5:3
4->5:5
max_flow=8
代码
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
//标号法求矩阵网络最大流
const int maxn=100;//顶点数量
const int INF=0x3f3f3f3f;
struct node
{
int c;//容量
int f;//流量
} map[maxn][maxn];
int flag[maxn];//未访问标记为-1,已访问未检查邻接顶点标记为0,已访问已检查邻接顶点标记为1
int prev[maxn];//i号顶点从prev[i]号顶点来
int alpha[maxn];//当star指向i,alpha[i]=min(alpha[star],map[star][i].c-map[star][i].f)
//当i指向star,alpha[i]=min(alpha[star],map[i][star].f);
int queue[maxn];//模拟队列
int N;//顶点
int M;//弧数
int q_star,q_end;//队列头尾指针
void ford()
{
while(1)//标号法可以在有限次标号调整后使求得最大流
{
for(int i=0; i<N; i++) //初始化三个辅助数组
{
flag[i]=-1;
prev[i]=-1;
alpha[i]=-1;
}
flag[0]=0;//源点标记为已访问未检查的点
prev[0]=0;//源点的上一个点还是源点
alpha[0]=INF;//源点可以无限流出
q_star=q_end=0;
queue[q_end++]=0;//源点入队
while(q_star<q_end&&flag[N-1]==-1)//队列内有元素或者还没标记到汇点时进入循环接着标记
{
int star=queue[q_star++];//去除队列元素
for(int i=0; i<N; i++) //检查star的邻接顶点,由于是有向图,所以需要检查正向邻接和反向邻接
{
if(flag[i]==-1)//只检查尚未访问过的点,因为已访问未检查的点都在队列中
{
//检查正向邻接,存在此弧且流量未满
if(map[star][i].c<INF&&map[star][i].f<map[star][i].c)
{
flag[i]=0;//标记为已访问未检查
prev[i]=star;//记录增广路径
alpha[i]=min(alpha[star],map[star][i].c-map[star][i].f);//可调整量
queue[q_end++]=i;//顶点i入队
}
//检查反向邻接,存在弧且有流量
if(map[i][star].c<INF&&map[i][star].f>0)
{
flag[i]=0;//标记为已访问未检查
prev[i]=-star;//加个负号表示反向邻接
alpha[i]=min(alpha[star],map[i][star].f);//可调整量
queue[q_end++]=i;//入队
}
}
}
flag[star]=1;//标记为已访问已检查
}
if(flag[N-1]==-1||alpha[N-1]==0)//如果找不到去汇点的增广路径或者可调整量为0
break;//结束标号法
//下面这一步可能有问题
int alpha_num=alpha[N-1];//可调整量
int k1=N-1;
int k2=abs(prev[k1]);
while(1)
{
if(map[k2][k1].f<INF)
map[k2][k1].f+=alpha_num;
else
map[k1][k2].f-=alpha_num;
if(k2==0)//当调整到源点时跳出循环
break;
k1=k2;
k2=abs(prev[k2]);//不要忘了取绝对值
}
}
//下面输出各弧边最大流并累加
int max_flow=0;//累加各弧最大流
for(int i=0; i<N; i++)
{
for(int j=0; j<N; j++)
{
if(i==0&&map[i][j].f<INF)
max_flow+=map[i][j].f;
if(map[i][j].f<INF)
printf("%d->%d:%d\n",i,j,map[i][j].f);
}
}
printf("max_flow=%d\n",max_flow);
}
int main()
{
scanf("%d%d",&N,&M);
for(int i=0; i<N; i++)
for(int j=0; j<N; j++)
map[i][j].c=map[j][i].f=INF;//网络流都是有向图
int u,v,c,f;
for(int i=0; i<M; i++)
{
scanf("%d%d%d%d",&u,&v,&c,&f);
map[u][v].c=c;
map[u][v].f=f;
}
ford();
return 0;
}