博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
最小费用最大流算法
阅读量:3967 次
发布时间:2019-05-24

本文共 4225 字,大约阅读时间需要 14 分钟。

最小费用最大流算法

代码实现

/*参考:《趣学算法》陈小玉 人民邮电出版社最小费用最大流---最小费用路算法问题分析:    在实际应用中,要同时考虑流量和费用,每条边除了给定容量之外,    还定义了一个单位流量的费用.    网络流的费用=每条边的流量*单位流量费用    我们希望费用最小,流量最大,因此要求解最小费用最大流      容量 流量  单位流量费用        (cap,flow,cost)    v1--------------------->v2    混合网络    每个顶点有        (3,2,1)    v1--------------------->v2    v1<---------------------v2        (0,-2,-1)算法过程:    (1)先找最小费用路,在该路径上增流,称为最小费用路算法。    (2)先找最大流,然后找负费用圈,消减费用,减少到最小费用,称为消圈法    最小费用路算法,是在残余网络上寻找从源点到汇点的最小费用路,即从源点到汇点的    以单位费用为权的最短路,然后沿着最小费用路增流,知道找不到最小费用路为止。*/#include
#include
#include
#include
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<<"网络的最小费用:"<
<
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"<
<<" ["<
0){ cout<<"v"<
<<"--"<<"v"<
<<" "<
<<" "<
<<"\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<<"增广路径: "<
v u<----v u---->v u<---v,通俗些就是u-->v就v<---u v<--u u-->v d=min(d,E[i].cap-E[i].flow);//迭代找最小可增量 cout<<"--"<
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--->x for(int i=V[u].first;i!=-1;i=E[i].next){ v=E[i].v;//u---->v if(E[i].cap>E[i].flow && dist[v]>dist[u]+E[i].cost){ //松弛操作:这条边还可以增流且借助u-->v比直接到v cost少,如果不可增流则这条边不连通 //更新源点--->v cost dist[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<<" "<

测试样例

请输入 结点个数 和 边数:6 10请输入两个结点u,v,边u---v的容量weight,单位容量费用cost:1 3 4 71 2 3 12 5 4 52 4 6 42 3 1 13 5 3 63 4 5 34 6 7 65 6 3 25 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 100000088网络的最大流值: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 1v1--v3 4 7v2--v5 3 5v3--v4 4 3v4--v6 4 6v5--v6 3 2

转载地址:http://oucki.baihongyu.com/

你可能感兴趣的文章
Linux设备驱动调试技术 2
查看>>
Linux设备驱动调试技术 2
查看>>
Linux设备驱动调试技术 3
查看>>
Linux设备驱动调试技术 3
查看>>
java&nbsp;访问&nbsp;usb&nbsp;(一)
查看>>
java&nbsp;访问&nbsp;usb&nbsp;(一)
查看>>
linux-2.6.14下USB驱动移植心得
查看>>
linux-2.6.14下USB驱动移植心得
查看>>
[S3C6410]USB-HOST驱动完成
查看>>
[S3C6410]USB-HOST驱动完成
查看>>
Linux模块编程系列之二&nbsp;熟悉特定的…
查看>>
Linux模块编程系列之二&nbsp;熟悉特定的…
查看>>
Linux2.6内核驱动移植参考
查看>>
Linux2.6内核驱动移植参考
查看>>
设备标识及驱动程序所支持的设备(…
查看>>
设备标识及驱动程序所支持的设备(…
查看>>
EXPORT_SYMBOL()
查看>>
EXPORT_SYMBOL()
查看>>
在fedora9中编译linux设备驱动程序…
查看>>
在fedora9中编译linux设备驱动程序…
查看>>