最大流—最小割的C++实现

     最大流与最小割是图论里最经典的算法之一:为了实现这个算法,储存方面我用的是图的邻接表而不是邻接矩阵,因为我觉得邻接表效率会更快一点,而算法方面我用的是广度优先搜索,这种方法效率也是比较高的,下面就是我的算法的c++实现:


#include<iostream>
#include<queue>
#include<vector>
#include<cmath>
#include<stdio.h>
#define MAX 999999
using namespace std;

class Graph
{
private:
	struct vertex
	{
	  int num   ;               //编号
	  int flag  ;              //正向或负向标记
	  int ver   ;             //来自哪条边
	  int flow;               //流量标记
	  vector<int>f_edge ;     //前向边
	  vector<int>u ;         //前向边的流量
	  vector<int>b_edge;      //后向边
	  vector<int>x ;        //后向边的流量
	  vertex(int num,int flag,int flow):num(num),flag(flag),flow(flow){	  //  u.push_back(0);	x.push_back(0);
	  }
	};
  int N;                    //边数
  vector<vertex>v;
  public:
  Graph(int n):N(n)
  {
      for(int i=0;i<=n;i++)
	  {
		  vertex tmp(i,0,0);
		  v.push_back(tmp);
         for(int j=0;j<=n;j++)
          {
             v[i].u.push_back(0);
             v[i].x.push_back(0);
          }
	  }

 	  v[1].flag=-1;         //源点标记为-1
 	  v[1].flow=MAX;

  }
  void Edge_flow(int i,int j,int flow)
  {	  v[i].f_edge.push_back(j);
      v[i].u[j]=flow;
	  v[j].b_edge.push_back(i);
  }
  int  Max_flow()
  {

     queue<int>Q;
     Q.push(1);
     int max_f=0;
     while(!Q.empty())
     {
        int i=Q.front();Q.pop();
        int l=v[i].flow;
        for(unsigned int k=0;k<v[i].f_edge.size();k++)
         {
            int j=v[i].f_edge[k];
            if(v[j].flag==0)
              {

                  int r=v[i].u[j]-v[i].x[j];
                  if(r>0)
                  {
                     l=min(l,r);
                     v[j].flag=1;v[j].ver=i;v[j].flow=l;
                     Q.push(j);
                  }
              }
         }
        for(unsigned int k=0;k<v[i].b_edge.size();k++)
         {
            int j=v[i].b_edge[k];
            if(v[j].flag==0)
              {
                  int r=v[j].x[i];
                  if(r>0)
                  {
                     l=min(l,r);
                     v[j].flag=-1;v[j].ver=i;v[j].flow=l;
                     Q.push(j);
                  }
              }
         }
         if(v[N].flag!=0)
         {
            int j=N;
            max_f+=l;
            cout<<"One of the path is :";
            while(j!=1)
            {
              cout<<j<<" from ";
               int k=v[j].ver;
                if(v[j].flag==1)
                  v[k].x[j]+=l;
                if(v[j].flag==-1)
                  v[j].x[k]-=l;
                j=k;
            }
            cout<<1<<" and the flow is "<<l<<endl;
            while(!Q.empty())
             Q.pop();
            for(int i=2;i<=N;i++)
             v[i].flag=0;
             Q.push(1);
         }

     }
     return max_f;

  }
  void Min_cut()
  {
    for(int i=1;i<N;i++)
    {
       if(v[i].flag!=0)
       {
       for(unsigned int k=0;k<v[i].f_edge.size();k++)
          {
            int j=v[i].f_edge[k];
            if(v[j].flag==0&&v[i].flag!=0)
                 cout<<"("<<i<<","<<j<<")"<<";  ";
           }
        }
     }

  }

};
int main()
{
     freopen("in.txt","r",stdin);
     freopen("out.txt","w",stdout);
     int ver;

     while(cin>>ver)
     {
      Graph G(ver);
      int edge;
      cin>>edge;
      int i,j,flow;
      while(edge--)
      {
         cin>>i>>j>>flow;javascript:;
         G.Edge_flow(i,j,flow);
      }
      cout<<"The max_flow is :"<<G.Max_flow()<<endl;
      cout<<"One of the min_cut is :";
      G.Min_cut();
      cout<<endl;
      }
     fclose(stdin);
     fclose(stdout);
      return 0;
}



接下来是in.txt里的测试数据,如下:

6 
7
1 2 2
1 4 3
2 5 3
2 3 5
4 3 1
3 6 2
5 6 4
4
5
1 2 100
1 3 10
2 3 100
3 4 10
2 4 1000
6
7
1 2 5
1 3 6
2 5 2
2 4 4
3 4 7
4 6 8
5 6 4
6
8
1 2 2
1 3 7
2 4 3
2 5 4
3 4 4
3 5 2 
4 6 1
5 6 5
 
 

下面是out.txt的输出结果,如下

One of the path is :6 from 5 from 2 from 1 and the flow is 2
One of the path is :6 from 3 from 4 from 1 and the flow is 1
The max_flow is :3
One of the min_cut is :(1,2);  (4,3);  
One of the path is :4 from 2 from 1 and the flow is 100
One of the path is :4 from 3 from 1 and the flow is 10
The max_flow is :110
One of the min_cut is :(1,2);  (1,3);  
One of the path is :6 from 5 from 2 from 1 and the flow is 2
One of the path is :6 from 4 from 2 from 1 and the flow is 3
One of the path is :6 from 4 from 3 from 1 and the flow is 3
One of the path is :6 from 4 from 3 from 1 and the flow is 2
The max_flow is :10
One of the min_cut is :(2,5);  (4,6);  
One of the path is :6 from 4 from 2 from 1 and the flow is 1
One of the path is :6 from 5 from 2 from 1 and the flow is 1
One of the path is :6 from 5 from 3 from 1 and the flow is 2
One of the path is :6 from 5 from 2 from 4 from 3 from 1 and the flow is 1
The max_flow is :5
One of the min_cut is :(1,2);  (3,5);  (4,6); 

可以看到,测试数据是没有问题的,这说明我的代码也应该没有什么问题;再根据分析,广度优先搜索效率是O(nm^2)的,空间消耗是O(n^2).

 


  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值