最小费用最大流算法 网络流

article/2025/9/28 19:33:28

最小费用最大流算法

在这里插入图片描述
图片来源 《趣学算法》 人民邮电出版社 陈小玉

代码实现

/*
参考:《趣学算法》陈小玉 人民邮电出版社
最小费用最大流---最小费用路算法
问题分析:在实际应用中,要同时考虑流量和费用,每条边除了给定容量之外,还定义了一个单位流量的费用.网络流的费用=每条边的流量*单位流量费用我们希望费用最小,流量最大,因此要求解最小费用最大流容量 流量  单位流量费用(cap,flow,cost)v1--------------------->v2混合网络每个顶点有(3,2,1)v1--------------------->v2v1<---------------------v2(0,-2,-1)
算法过程:(1)先找最小费用路,在该路径上增流,称为最小费用路算法。(2)先找最大流,然后找负费用圈,消减费用,减少到最小费用,称为消圈法最小费用路算法,是在残余网络上寻找从源点到汇点的最小费用路,即从源点到汇点的以单位费用为权的最短路,然后沿着最小费用路增流,知道找不到最小费用路为止。
*/
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;const int INF=1000000;//正无穷
const int NODESIZE=100;//结点最大个数
const int EDGESIZE=10000;//最大边数
int top;//当前边下标
int maxflow;//最大流
bool vis[NODESIZE];//访问标记数组
int c[NODESIZE];//入队次数
int dist[NODESIZE];//dist[i]表示源点到点i最短距离:距离即这条路单位cost和
int pre[NODESIZE];//前驱数组struct Vertex{//邻接表头节点int first;//与之连接的边的序号
}V[NODESIZE];
struct Edge{//边表示int v,next;//v弧头 next指向下一条邻接边int cap,flow,cost;
}E[EDGESIZE];void init();//初始化
void add(int u,int v,int c,int cost);//更新混合网络
void add_edge(int u,int v,int c,int cost);//更新混合网络边
void printgraph(int n);//输出网络邻接表
void printflow(int n);//输出实流边
int MCMF(int s,int t,int n);//最小花费最大流
bool SPFA(int s,int t,int n);//求最小费用路int main(void){int nodeSize,edgeSize;int unode,vnode,weight,cost;cout<<"请输入 结点个数 和 边数: \n";cin>>nodeSize>>edgeSize;//初始化init();cout<<"请输入两个结点u,v,边u---v的容量weight,单位容量费用cost:\n";for(int i=1;i<=edgeSize;i++){cin>>unode>>vnode>>weight>>cost;add(unode,vnode,weight,cost);}//输出网络邻接表printgraph(nodeSize);cout<<"网络的最小费用:"<<MCMF(1,nodeSize,nodeSize)<<endl;cout<<"网络的最大流值:"<<maxflow<<endl;//输出最终网络printgraph(nodeSize);//输出实流变printflow(nodeSize);return 0;
}//初始化
void init(){memset(V,-1,sizeof(V));//初始化顶点top=0;//当前边下标maxflow=0;
}//更新混合网络
void add(int u,int v,int c,int cost){add_edge(u,v,c,cost);add_edge(v,u,0,-cost);
}//更新混合网络边
void add_edge(int u,int v,int c,int cost){//    top    top.v//u---------->v //构建邻接表:头插法 顺序存储法E[top].v=v;E[top].cap=c;E[top].flow=0;E[top].cost=cost;E[top].next=V[u].first;//.next记录链的结点,下一个边的下标V[u].first=top++;//顺序存储拉链
}
//输出网络邻接表
void printgraph(int n){cout<<"\n网络邻接表\n";for(int i=1;i<=n;i++){cout<<"v"<<i<<" ["<<V[i].first;for(int j=V[i].first;~j;j=E[j].next){cout<<"]--["<<E[j].v<<"  "<<E[j].cap<<"  "<<E[j].flow<<" "<<E[j].cost<<" "<<E[j].next<<"]\n";}cout<<"\n";}
}
//输出实流边
void printflow(int n){cout<<"实流边:\n";for(int i=1;i<=n;i++){for(int j=V[i].first;~j;j=E[j].next){if(E[j].flow>0){cout<<"v"<<i<<"--"<<"v"<<E[j].v<<" "<<E[j].flow<<" "<<E[j].cost<<"\n";}}}
}
//最小花费最大流
int MCMF(int s,int t,int n){int d;//可增量int i,mincost;mincost=0;//maxflow为网络当前最大流量,mincost为网络当前最小费用while(SPFA(s,t,n)){//有从s到t的最小费用路d=INF;//初始化增流量cout<<"增广路径: "<<t;               //             i       i^1     i       i+1            i      i+1=i^1   i    i-1=i^1for(i=pre[t];i!=-1;i=pre[E[i^1].v]){//i=pre[u.v] u---->v u<----v u---->v u<---v,通俗些就是u-->v就v<---u   v<--u u-->vd=min(d,E[i].cap-E[i].flow);//迭代找最小可增量cout<<"--"<<E[i^1].v;}cout<<"\n";cout<<"增流量: "<<d<<"\n";//更新最大流maxflow+=d;//增广路上正向边流量+d 反向边流量-dfor(int i=pre[t];i!=-1;i=pre[E[i^1].v]){E[i].flow+=d;E[i^1].flow-=d;}mincost+=dist[t]*d;//源点到t的单位花费*新增的流量}return mincost;
}
//求最小费用路
bool SPFA(int s,int t,int n){int u,v;queue<int>qu;//队列memset(vis,false,sizeof(vis));//标记结点是否已经访问过了memset(c,0,sizeof(c));//入队次数memset(pre,-1,sizeof(pre));//前驱数组初始化为-1//距离初始化:源点到各个结点的最短距离for(int i=1;i<=n;i++){dist[i]=INF;}//源点入队vis[s]=true;c[s]++;dist[s]=0;qu.push(s);while(!qu.empty()){//取队头,并消除标记u=qu.front();qu.pop();vis[u]=false;//遍历结点u的邻接表:即遍历u的所有出度边u--->xfor(int i=V[u].first;i!=-1;i=E[i].next){v=E[i].v;//u---->vif(E[i].cap>E[i].flow && dist[v]>dist[u]+E[i].cost){//松弛操作:这条边还可以增流且借助u-->v比直接到v cost少,如果不可增流则这条边不连通//更新源点--->v costdist[v]=dist[u]+E[i].cost;//记录v的前驱,pre记录的是边-->v 通过这条边最短到v 则v的前驱为这条边的下标pre[v]=i;//检测v是否在队列内if(!vis[v]){//不在//v结点入队列c[v]++;qu.push(v);//入队vis[v]=true;if(c[v]>n){//超过入队上上限,则说明有负环return false;}}}}}//最短可增流路径cout<<"最短可增流路径数组:\n";cout<<"dist[]=>";for(int i=1;i<=n;i++){cout<<" "<<dist[i];}cout<<"\n";if(dist[t]==INF){//如果源点到汇点距离为正无穷,则不通:找不出最短可通路径return false;}return true;
}

测试样例

请输入 结点个数  边数:
6 10
请输入两个结点u,v,边u---v的容量weight,单位容量费用cost:
1 3 4 7
1 2 3 1
2 5 4 5
2 4 6 4
2 3 1 1
3 5 3 6
3 4 5 3
4 6 7 6
5 6 3 2
5 4 3 3网络邻接表
v1 [2]--[2  3  0 1 0]
]--[3  4  0 7 -1]v2 [8]--[3  1  0 1 6]
]--[4  6  0 4 4]
]--[5  4  0 5 3]
]--[1  0  0 -1 -1]v3 [12]--[4  5  0 3 10]
]--[5  3  0 6 9]
]--[2  0  0 -1 1]
]--[1  0  0 -7 -1]v4 [19]--[5  0  0 -3 14]
]--[6  7  0 6 13]
]--[3  0  0 -3 7]
]--[2  0  0 -4 -1]v5 [18]--[4  3  0 3 16]
]--[6  3  0 2 11]
]--[3  0  0 -6 5]
]--[2  0  0 -5 -1]v6 [17]--[5  0  0 -2 15]
]--[4  0  0 -6 -1]网络的最小费用:最短可增流路径数组:
dist[]=> 0 1 2 5 6 8
增广路径: 6--5--2--1
增流量: 3
最短可增流路径数组:
dist[]=> 0 8 7 10 13 16
增广路径: 6--4--3--1
增流量: 4
最短可增流路径数组:
dist[]=> 0 1000000 1000000 1000000 1000000 1000000
88
网络的最大流值:7网络邻接表
v1 [2]--[2  3  3 1 0]
]--[3  4  4 7 -1]v2 [8]--[3  1  0 1 6]
]--[4  6  0 4 4]
]--[5  4  3 5 3]
]--[1  0  -3 -1 -1]v3 [12]--[4  5  4 3 10]
]--[5  3  0 6 9]
]--[2  0  0 -1 1]
]--[1  0  -4 -7 -1]v4 [19]--[5  0  0 -3 14]
]--[6  7  4 6 13]
]--[3  0  -4 -3 7]
]--[2  0  0 -4 -1]v5 [18]--[4  3  0 3 16]
]--[6  3  3 2 11]
]--[3  0  0 -6 5]
]--[2  0  -3 -5 -1]v6 [17]--[5  0  -3 -2 15]
]--[4  0  -4 -6 -1]实流边:
v1--v2 3 1
v1--v3 4 7
v2--v5 3 5
v3--v4 4 3
v4--v6 4 6
v5--v6 3 2

http://chatgpt.dhexx.cn/article/7OOd7Oq3.shtml

相关文章

网络流----最小费用最大流(EK+SPFA)

先来介绍一下什么是费用流&#xff08;部分内容参考bilibili董晓算法&#xff09; 给定一个网络G&#xff08;V&#xff0c;E&#xff09;&#xff0c;每条边有容量限制w(u,v)&#xff0c;还有单位流量的费用c(u,v)。 当&#xff08;u,v&#xff09;的流量为f(u,v)时&#xf…

【图论】网络流——最大流和最小费用流

【图论】网络流——最大流和最小费用流 文章目录 【图论】网络流——最大流和最小费用流1. 最大流问题1.1 基本概念1.2 寻求最大流的算法&#xff08;Ford-Fulerson&#xff09;1.3 matlab求最大流 2. 最小流问题2.1 基本概念2.2 求最小流的迭代算法2.3 matlab 求最大费用最小流…

网络流(2)-----最小费用最大流(附带讲解SPFA算法)

一.最小费用最大流&#xff08;简称费用流&#xff09;概念 1.什么是费用流问题 上篇文章我们讲解了最大流问题&#xff0c;那什么是最小费用最大流呢&#xff1f;听名字就可以看出&#xff0c;我们要在满足最大流的同时找到达成最大流的最小费用。对于一个网络流&#xff0c…

最小费用最大流问题详解

最小费用最大流问题 一、问题描述 在网络中求一个最大流f&#xff0c;使流的总输送费用最小。 b ( f ) ∑ ( v i , v j ) b i j f i j b(f) \sum\limits_{(v_i,v_j)} b_{ij} f_{ij} b(f)(vi​,vj​)∑​bij​fij​ ) &#xff08; b i j b_{ij} bij​ 表示弧 ( v i , v j…

最小费用最大流问题与算法实现(Bellman-Ford、SPFA、Dijkstra)

摘要 今日&#xff0c;对最小费用最大流问题进行了一个简单的研究&#xff0c;并针对网上的一些已有算法进行了查找和研究。博客和资料很多&#xff0c;但是留下的算法很多运行失败、出错&#xff0c;或者意义不明。这里&#xff0c;个人对其中的Bellman-Ford、SPFA、改进的Di…

如何区分冲突域和广播域?

举个例子&#xff0c;原始社会的人都生活在山洞里&#xff0c;每个人都住在自己的山洞里&#xff0c;洞穴的中间只有一个狭长的走廊可以出去&#xff0c;平时出去玩&#xff0c;大哥都会喊一嗓子&#xff0c;有人出去打猎不&#xff0c;所有人都听得到&#xff0c;这就是一个广…

冲突域和广播域区别

一、区别 1、广播域就是说如果站点发出一个广播信号后能接收到这个信号的范围。通常来说一个局域网就是一个广播域。冲突域指一个站点向另一个站点发出信号。除目的站点外&#xff0c;有多少站点能收到这个信号。这些站点就构成一个冲突域。 2、冲突域通过集线器连接&#xf…

冲突域和广播域区别,集线器、交换机和路由器对比

冲突域 我们把以太网想象为对讲机&#xff0c;电脑想象为使用对讲机的人&#xff0c;数据传输想象为使用对讲机说话。现在一群人打真人CS&#xff0c;两个及以上的人同时通过对讲机说话&#xff0c;就听不清在说什么了&#xff0c;这就是冲突。对讲机通道只能一人单独使用。对…

冲突域和广播域; 集线器、交换机以及路由器比较

转自https://blog.csdn.net/gui951753/article/details/79402528#1%E5%B7%A5%E4%BD%9C%E5%B1%82%E6%AC%A1%E4%B8%8D%E5%90%8C 目录 冲突域和广播域 联网中继设备 集线器&#xff08;hub&#xff09; 交换机(switch) 路由器(route) 三者的异同 冲突域和广播域 在介绍这三…

交换机基础原理,冲突域和广播域

交换机的基本定义 提供了大量的接入端口&#xff0c;能够很好的满足大量用户接入到网络中的需求。 在OSI模型的二层&#xff0c;数据链路层&#xff1b; 可以识别数据包中的MAC地址信息&#xff0c;根据MAC地址进行转发数据&#xff0c;并且会将这些MAC地址与对应的端口记录在…

冲突域和广播域的区分

一、概念理解&#xff1a; 1、冲突域&#xff08;物理分段&#xff09;&#xff1a; 连接在同一导线上的所有工作站的集合&#xff0c;或者说是同一物理网段上所有节点的集合或以太网上竞争同一带宽的节点集合。这个域代表了冲突在其中发生并传播的区域&#xff0c;这个区域可…

冲突域和广播域的区别

冲突域 冲突域指的是会产生冲突的最小范围&#xff0c;在计算机和计算机通过设备互联时&#xff0c;会建立一条通道&#xff0c;如果这条通道只允许瞬间一个数据报文通过&#xff0c;那么在同时如果有两个或更多的数据报文想从这里通过时就会出现冲突了。 冲突域的大小可以衡…

冲突域和广播域

冲突域&#xff1a; 冲突域是信道的争抢&#xff0c;信道只有一条&#xff0c;A在使用&#xff0c;B就不可以使用&#xff0c;这样就会产生冲突&#xff0c;这就是冲突域的产生 在一个信道上的所有主机组成一个冲突域&#xff0c;划分网络越小越好&#xff0c;不会引起很大的冲…

如何理解冲突域和广播域?(转)

如何理解冲突域和广播域&#xff1f;&#xff08;转&#xff09; 转自&#xff1a;http://blog.sina.com.cn/s/blog_7e8dec240102wyio.html 网上看到的好文章&#xff0c;整理下来&#xff0c;方便复习&#xff0c;侵删 1、冲突域&#xff1a; 【定义】在同一个冲突域中的每…

设备划分冲突域和广播域

冲突域是一种物理分段&#xff0c;指连接到同一导线上所有工作站的集合、同一物理网段上所有节点的集合或是以太网上竞争同一带宽节点的集合。冲突域表示冲突发生并传播的区域&#xff0c;这个区域可以被认为是共享段。在OSI模型中&#xff0c;冲突域被看作是OSI第一层的概念&a…

HCIA—冲突域与广播域(详解 + 区别)

目录 一、冲突域&#xff1a; &#xff08;1&#xff09;HUB组网&#xff1a; &#xff08;2&#xff09;冲突域 概述 特点&#xff1a; 二、广播域&#xff1a; &#xff08;1&#xff09;广播域 概述特点&#xff1a; 三、冲突域 与 广播域的区别与联系&#xff1a; 一…

网络基础之冲突域和广播域

温故&#xff1a; 前面的几天 &#xff0c;主要讲了OSI网络七层的相关知识&#xff0c;着重的分析了每一层所具备的功能和服务&#xff0c;在这里我再次强调一遍&#xff1a;功能指的是本层的作用&#xff0c;服务指的是本层能为上层提供的业务&#xff0c;至于协议则是定义了每…

广播域和冲突域

在准备软考的时候将广播域看成了广域网,结果就错了一道题,这篇文章就从这道错题开始... 1.广播域和冲突域的定义 广播域:网络中能接受任一设备发出的广播帧的设备的集合. 冲突域:在同一个网络内,如果任意两台计算机在同时通信是会发生冲突,那么它们所组成的网络就是一个冲突域…

计算机网络 —— 冲突域和广播域

一、概念 &#xff08;1&#xff09;冲突域 定义&#xff1a;同一时间内只能有一台设备发送信息的范围。 分层&#xff1a;基于OSI的第一层物理层 设备&#xff1a;第二层设备能隔离冲突域&#xff0c;比如Switch。交换机能缩小冲突域的范围&#xff0c;交换接的每一个端口就…

冲突域与广播域

冲突域是一种物理分段&#xff0c;指连接到同一导线上所有工作站的集合、同一物理网段上所有节点的集合或是以太网上竞争同一带宽节点的集合。冲突域表示冲突发生并传播的区域&#xff0c;这个区域可以被认为是共享段。在OSI模型中&#xff0c;冲突域被看作是OSI第一层的概念&a…