关于网络流算法

author author     2022-08-26     672

关键词:

实现MCMF的基础上进行尝试针对题目修改代码就方便许多,这里的一个难点是如何输出MCMF对应的各条流路径(网络路径)。实现了MCMF之后很长的一段时间我一直在走弯路,最后发现是自己的测试数据并不方便手算而且一开始采用的模板本身有错误,另一方面因为我之前并没有接触过图论算法,对这些现学的算法实现和运行细节不熟悉。在调整心态之后我决定使用自己设计的图作为调试用例并慢节奏地调试理解,稳扎稳打。

这里有一个博客,作者的思路与我一致,其内容对我有很大帮助。

 

2.1 多服务器(固定)-多消费结点、无输出的版本

这是调试的一个版本,作为算法发展的基础。

技术分享
  1 #include<iostream>
  2 #include<string.h>
  3 #include<vector>
  4 #include<queue>
  5 #include<algorithm>
  6 using namespace std;
  7 
  8 const int maxm=10000+100;    //最大点数
  9 const int INF=0x3f3f3f3f;
 10 
 11 struct edge{        //边:起点、终点、容量、流量、单位费用
 12     int from,to,c,f,cost;
 13     edge(int a,int b,int m,int n,int p):from(a),to(b),c(m),f(n),cost(p){}
 14 };
 15 
 16 int aabs(int a){
 17     return a>=0?a:-a;
 18 }
 19 
 20 struct MCMF{
 21     int m,s,t;
 22     vector<edge> e;
 23     vector<int> g[maxm];
 24     int dis[maxm],a[maxm],p[maxm];
 25     bool vis[maxm];
 26 
 27     void init(int n){        //初始化函数
 28         for(int i=0;i<=n;i++)g[i].clear();
 29         e.clear();
 30     }
 31 
 32     void add(int a,int b,int c,int v){    //加边函数
 33         e.push_back(edge(a,b,c,0,v));
 34         e.push_back(edge(b,a,0,0,-v));
 35         m=e.size();
 36         g[a].push_back(m-2);
 37         g[b].push_back(m-1);
 38     }
 39 
 40     bool spfa(int& flow,int& cost){
 41         memset(dis,0x3f,sizeof(dis));
 42         memset(vis,0,sizeof(vis));
 43         queue<int>q;
 44         q.push(s);
 45         vis[s]=1;
 46         dis[s]=0;
 47         p[s]=0;
 48         a[s]=INF;
 49         while(!q.empty()){
 50             int u=q.front();q.pop();
 51             vis[u]=0;
 52             for(int i=0;i<g[u].size();i++){
 53                 edge tmp=e[g[u][i]];
 54                 if(dis[tmp.to]>dis[u]+tmp.cost &&tmp.c>tmp.f){
 55                     dis[tmp.to]=dis[u]+tmp.cost;
 56                     p[tmp.to]=g[u][i];
 57                     a[tmp.to]=min(a[u],tmp.c-tmp.f);
 58                     if(!vis[tmp.to]){
 59                         q.push(tmp.to);
 60                         vis[tmp.to]=1;
 61                     }
 62                 }
 63             }
 64         }
 65         if(dis[t]==INF)return 0;
 66         flow+=a[t];
 67         cost+=dis[t]*a[t];
 68         int u=t;
 69         while(u!=s){
 70             e[p[u]].f+=a[t];
 71             e[p[u]^1].f-=a[t];
 72             u=e[p[u]].from;
 73         }
 74         return 1;
 75     }
 76 
 77     void MF(int s,int t,int &flow,int &cost){    //调用的计算最小费用函数
 78         this->s=s;
 79         this->t=t;
 80         //int flow=0,cost=0;
 81         while(spfa(flow,cost));
 82         //return cost;
 83     }
 84 
 85 };
 86 
 87 int main()
 88 {
 89     freopen("C:\\Users\\lenovo\\Desktop\\工作\\华为挑战赛\\testCase0\\testCase4.txt", "r", stdin);
 90     
 91     //数据准备 
 92     int n, m, s, t, h;
 93     int from, to, cap, value;
 94     int flow, cost, need;
 95     int loc[maxm], k;
 96     MCMF mcmf;
 97     
 98     //输入第一行 
 99     cin>>n>>m>>h;
100     //初始化 
101     mcmf.init(n+h+2);
102     //输入网络节点并且add 
103     for( int i=1; i<=m; i++ )
104     {
105         cin>>from>>to>>cap>>value;
106         mcmf.add(from, to, cap, value);
107         mcmf.add(to, from, cap, value);
108     }
109     //输入消费结点、add零费用边、建立超级汇点 
110     for( int i=1; i<=h; i++ )
111     {
112         cin>>to>>from>>cap;
113         mcmf.add(from, to+n, cap, 0);
114         mcmf.add(to+n, from, cap, 0); 
115         
116         mcmf.add(to+n, n+h+1, cap, 0);    //汇点编号为 n+h+1 
117         mcmf.add(n+h+1, to+n, cap, 0);
118     }
119     //建立超级源点(以0结点为服务器)
120     k=2;
121     memset(loc,-1,sizeof(loc));
122     loc[0]=0;    loc[1]=1;
123     for(int i=0;i<k;i++)
124     {
125         mcmf.add(n+h+2, loc[i], cap, 0);    //源点编号为 n+h+2
126         mcmf.add(loc[i], n+h+2, cap, 0);
127     }
128     
129     mcmf.MF(n+h+1,n+h+2,flow,cost);
130     cout<<"flow= "<<flow<<endl<<"cost= "<<cost<<endl;
131     
132     fclose(stdin);
133 }
134 //多(固定)服务器单消费节点,含有超级结点 
View Code
技术分享
10 14 2

0 1 1 2
0 9 2 3
1 2 3 1
1 4 4 2
4 9 5 3
9 8 6 1
4 2 7 2
2 6 8 3
4 5 9 1
5 6 10 3
8 6 11 1
6 7 12 2
6 3 13 3
7 3 14 2

0 2 100
1 9 100
View Data

技术分享

 

2.2 引进DSF函数

关于网络流算法

实现MCMF的基础上进行尝试针对题目修改代码就方便许多,这里的一个难点是如何输出MCMF对应的各条流路径(网络路径)。实现了MCMF之后很长的一段时间我一直在走弯路,最后发现是自己的测试数据并不方便手算而且一开始采用... 查看详情

最大流ek算法(转)

...为当前的最大流值。(粗体表明需要掌握的概念)  关于反向边:以下摘至HDOJ的课件和网上的:首先来看一下基本的网络流最大流模型。有n个点,有m 查看详情

poj3436acmcomputerfactory网络流北大acm/icpc竞赛训练(代码片段)

...什么反向边是对的呢,凭空加进来一条边真的大丈夫吗,关于这个有相关正确性的证明,我也说不清楚只能直觉上去理解。之后是Edmonds-Ka 查看详情

最大流——增广路算法

关于网络流的增广路算法,网上有很多详细介绍,这里是摘录的模板。详细请见:http://www.cnblogs.com/kuangbin/archive/2011/07/26/2117636.html1#include<iostream>2#include<iomanip>3#include<ctime>4#include<climits>5#incl 查看详情

km算法(代码片段)

网络流km算法什么是网络流?网络流指,存在一个源点s和一个汇点t的特殊有向无环图(TAG),虽然说有图会好很多但是毕竟我只是写着为了之后忘了有回顾的东西,而且好麻烦..那什么是网络流的最大流?网络流的最大流是指这个网... 查看详情

网络流之最大流算法

...          最大流 网络流的定义: 在一个网络(有流量)中有两个特殊的点,一个是网络的源点(s),流量只出不进,一个是网络的汇点 查看详情

isap网络流算法

...优化。SAP即Edmonds-Karp算法,其具体思路是通过不断向残存网络推送流量来计算整个网络的最大流。阅读本文要求掌握网络流的基础概念,不懂的出门左拐算法导论。ISAP的时间复杂度与EK算法一致,而EK算法的时间复杂度为min(O(E|f|... 查看详情

图论算法》关于最大流转最短路两三事

  又要来一篇高质量的博客了  这道题可以用BZOJ1001做例子,  首先我们来张图这张图有6个点,10条边,每条边都有边权。那么什么叫最大流最小割捏?解释如下在一个平面图中,能够从其实点到达终点的最大流量,等于... 查看详情

算法学习笔记(8.2):上下界网络流

上下界网络流目录上下界网络流无源汇可行流有源汇上下界可行流有源汇上下界最大流有源汇上下界最小流作者有话说前置知识以及更多芝士参考下述链接网络流合集链接:网络流上下界网络流是普通网络流的一种变体,对于网... 查看详情

最小费用最大流模板

...算法思想:寻找最大流的方法是从某个可行流出发,找到关于这个流的一条增广路P;沿着P调整f,对新的可行流又试图寻找关于它的增广路,循环直至 查看详情

算法学习笔记(8.1):网络最大流算法ek,dinic,isap(代码片段)

网络最大流前置知识以及更多芝士参考下述链接网络流合集链接:网络流目录网络最大流EK增广路算法DinicISAP作者有话说最大流,值得是在不超过管道(边)容量的情况下从源点到汇点最多能到达的流量抽象一点:使\\(\\sum_(S,v)\\... 查看详情

网络最大流算法—ek算法

前言EK算法是求网络最大流的最基础的算法,也是比较好理解的一种算法,利用它可以解决绝大多数最大流问题。但是受到时间复杂度的限制,这种算法常常有TLE的风险思想还记得我们在介绍最大流的时候提到的求解思路么?对... 查看详情

网络最大流算法—dinic算法及优化

前置知识网络最大流入门前言Dinic在信息学奥赛中是一种最常用的求网络最大流的算法。它凭借着思路直观,代码难度小,性能优越等优势,深受广大oier青睐思想$Dinic$算法属于增广路算法。它的核心思想是:对于每一个点,对... 查看详情

最大流算法(网络流问题)

最大流算法(网络流问题):对于流的概念是,我觉得就是管道;而管道就存在一种限制,大的管道的通量要小于等于小的管道的最大的通量。算法实现(基于DFS,我自己的思路):**按照DF... 查看详情

网络最大流dinic算法

一句话题意:给出一个网络图,以及其源点和汇点,求出其网络最大流//dinic算法;//时间复杂度O(V^2E);#include<bits/stdc++.h>#defineinf999999#definemaxn200000usingnamespacestd;intn,m,s,t;intans=0;structEdge{intto,next,w;};structEdgeedge[max 查看详情

最大网络流算法(代码片段)

最大网络流,需要的准备是:BFS,EK算法用pre数组记录前驱节点,用vis判断是否访问过用g二维数组表示残余网络,用f二维数组表示实际流网络下面这篇博客详细介绍了最大网络流:既然已经有了轮子,那我就不造了https://www.cnblo... 查看详情

板子网络流算法(代码片段)

1.Edmonds-Karp  算法:通过反向增光路+bfs求解最大流#include<bits/stdc++.h>usingnamespacestd;#defineLOACLfreopen("in","r",stdin);\freopen("out","w",stdout);#defineFASTIOios::sync_with_stdio(false);#def 查看详情

网络流的最大流和最小流是啥算法

参考技术A首先是网络流中的一些定义:V表示整个图中的所有结点的集合.E表示整个图中所有边的集合.G=(V,E),表示整个图.s表示网络的源点,t表示网络的汇点.对于每条边(u,v),有一个容量c(u,v)(c(u,v)>=0),如果c(u,v)=0,则表示(u,v)不存... 查看详情