#include <iostream> #include <queue> using namespace std; const int Maxn=100; //图最大的结点数 int pre[Maxn]; //保存前一个结点的序号 int v[Maxn]; //结点的流量的可增加量 int g[Maxn][Maxn]; //表示边的最大容量 int f[Maxn][Maxn]; //表示边的以用容量 //求最小值的函数 int min(const int val1,const int val2) { return val1<val2 ?val1:val2; } //利用广度优先的思想(邻接矩阵存储) int maxFlow() { int n=0; //n表示结点数 //初始化 memset(v,0,sizeof(v)); memset(f,0,sizeof(f)); cin>>n;
int s=0,t=n-1; //s为起点,t为终点 for(int i=0;i<n;++i) for(int j=0;j<n;++j) cin>>g[i][j]; int queTop=0; //队列的列首 while(true) { memset(pre,int(-1),sizeof(pre)); queue<int> que; pre[s]=s; v[s]=0x7fffffff; //起点无限制 que.push(s); //用广度优先搜索算法来寻找增广路 while(!que.empty()) { //取出队首元素 queTop=que.front(); que.pop(); for(int i=0;i<n;++i) { if(pre[i]<0) //小于0表示还没处理过 { //正向边 if(g[queTop][i]>f[queTop][i]) { v[i]=min(g[queTop][i]-f[queTop][i],v[queTop]); //流量增加量的计算 pre[i]=queTop; //前一个结点 que.push(i); } //反向边 if(f[i][queTop]>0) { v[i]=min(f[i][queTop],v[queTop]); pre[i]=queTop+n; //反向边pre保存的是原来queTop值加n的数,方便更新时 //判定是正向边还是反向边 que.push(i); } } } //说明终点已经处理了,已得到一条增广矩阵,跳出循环,进入调整工作 if(pre[t]>=0) break; } if(pre[t]<0) break; //说明找不到增广路经,这时的流就是最大流 //调整边的剩余权值 int p=0,q=t; int minval=v[t]; //从终点向前用minval进行调整 while(q!=s) { p=pre[q]; if(p>=n) { p-=n; f[q][p]-=minval;//说明这条边是反向边 } else f[p][q]+=minval;//说明这条边是正向边 q=p; } } //最后输出最大的流量 queTop=0; for(int i=0;i<n;++i) queTop+=f[s][i]; return queTop; } int main() { cout<<maxFlow()<<endl; } |