中转站有容量限制的运输问题&最小费用最大流问题

这是我们运筹学的大作业~贴的代码可以直接在vs上跑,也是我们最终的代码,数据矩阵也在里面,具体的题目、解释什么的,等我写完课程论文把论文贴上来…

借鉴的代码链接: link.

#include "stdio.h"
#include <iostream>
#include <algorithm>
#include <map>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>

#define max 5000
#define MAXN 5050
#define INF 0x3f3f3f3f

using namespace std;

int n, m, s, t;
int u, v, c, w;
int maxFlow, minCost;


struct Edge
{
	int from, to, flow, cap, cost;
};

bool vis[MAXN];
int p[MAXN], a[MAXN], d[MAXN],route[MAXN];
vector<int> g[MAXN];
vector<Edge> edges;

void init(int n)
{
	for (int i = 0; i <= n; i++)
		g[i].clear();
	edges.clear();
}
void addedge(int from, int to, int cap, int cost)
{
	Edge temp1 = { from, to, 0, cap, cost };
	Edge temp2 = { to, from, 0, 0, -cost };//允许反向增广
	edges.push_back(temp1);
	edges.push_back(temp2); //加进来两条边
	int len = edges.size();
	g[from].push_back(len - 2);
	g[to].push_back(len - 1);
}

//贝尔曼-福特算法实现
bool bellmanford(int s, int t)
{
	for (int i = 0; i < MAXN; i++)
	{
		d[i] = INF; route[i] = 0;
	}
	d[s] = 0;
	memset(vis, false, sizeof(vis));
	memset(p, -1, sizeof(p));
	p[s] = -1;
	a[s] = INF;
	queue<int> que;
	que.push(s);
	vis[s] = true;
	while (!que.empty())
	{
		int u = que.front();
		que.pop();
		vis[u] = false;
		for (int i = 0; i < g[u].size(); i++)
		{
			Edge& e = edges[g[u][i]];
			if (e.cap > e.flow && d[e.to] > d[u] + e.cost )//进行松弛,寻找最短路径也就是最小费用
			{
				route[e.to] = e.from;
				d[e.to] = d[u] + e.cost;
				p[e.to] = g[u][i];
				a[e.to] = min(a[u], e.cap - e.flow);
				if (!vis[e.to])
				{
					que.push(e.to);
					vis[e.to] = true;
				}
			}
		}
	}
	if (d[t] == INF)
		return false;
	
	maxFlow += a[t];
	minCost += d[t] * a[t];

	for (int i = t; i != s; i = edges[p[i]].from)
	{
		edges[p[i]].flow += a[t];
		edges[p[i] ^ 1].flow -= a[t];
	}
	return true;
}

void MCMF()
{
	while (bellmanford(s, t))
		continue;
	cout << endl;
	cout << "我要开始输出结果啦!" << endl;
	for (int i = 0; i < 20; i = i+2)
		cout << edges[i].flow << " ";
	cout << endl;
	for (int i = 20; i < 40; i=i+2)
		cout << edges[i].flow << " ";
	cout << endl;
	for (int i = 40; i < 74; i=i+2)
		cout << edges[i].flow << " ";
	cout << endl;
	cout << endl;
	return;
}


int main()
{

	cout << "节点数为:"; cin >> n;
	cout << "边数为:"; cin >> m;
	cout << "源点编号为:"; cin >> s;
	cout << "汇点编号为:"; cin >> t;

	/*int shuru[] = { 1,3,max,210, 1,4,120,185,
		1,8,max,210, 1,7,120,200,
		1,10,max,500, 1,9,120,410,
		1,11,120,620,
		1,6,max,470, 1,5,120,400,

		0,1,500,0, 0,2,300,0,
		2,3,max,230, 2,4,120,205,
		2,8,max,210, 2,7,120,200,
		2,10,max,280, 2,9,120,240,
		2,11,120,350,
		2,5,120,150, 2,6,max,160,

		3,8,max,100, 4,7,120,80,
		3,10,max,170, 4,9,120,150,
		4,11,120,250,
		4,5,120,135, 3,6,max,160,

		5,4,120,140, 6,3,max,160,
		5,7,120,270, 6,8,max,315,
		5,9,120,110, 6,10,max,130,
		5,11,120,130,
		7,12,max,0, 8,12,max,0,
		9,13,max,0, 10,13,max,0,
		12,14,300,0, 13,14,400,0, 11,14,100,0,

		3,4,max,0,4,3,max,0,
		5,6,max,0,6,5,max,0
	};*/

	/*int shuru[] = { 1,3,max,210, 1,4,120,185,
		1,8,max,210, 1,7,120,200,
		1,10,max,500, 1,9,120,410,
		1,11,120,620,
		1,6,max,470, 1,5,120,400,

		0,1,500,0, 0,2,300,0,
		2,3,max,230, 2,4,120,205,
		2,8,max,210, 2,7,120,200,
		2,10,max,280, 2,9,120,240,
		2,11,120,350,
		2,5,120,150, 2,6,max,160,

		17,8,max,100, 18,7,120,80,
		17,10,max,170, 18,9,120,150,
		18,11,120,250,
		18,5,120,135, 17,6,max,160,

		21,4,120,140, 22,3,max,160,
		21,7,120,270, 22,8,max,315,
		21,9,120,110, 22,10,max,130,
		21,11,120,130,

		7,12,max,0, 8,12,max,0,
		9,13,max,0, 10,13,max,0,
		12,14,300,0, 13,14,400,0, 11,14,100,0,

		3,15,max,0, 4,15,max,0,
		15,16,100,0, 
		16,17,max,0, 16,18,max,0,

		5,19,max,0, 6,19,max,0,
		19,20,80,0,
		20,21,max,0, 20,22,max,0
	};*/

	//简化版 不带容量限制
	/*int shuru[] = { 1,3,max,210, 1,3,120,185,
		1,7,max,210, 1,7,120,200,
		1,9,max,500, 1,9,120,410,
		1,11,120,620,
		1,5,max,470, 1,5,120,400,

		0,1,500,0, 0,2,300,0,
		2,3,max,230, 2,3,120,205,
		2,7,max,210, 2,7,120,200,
		2,9,max,280, 2,9,120,240,
		2,11,120,350,
		2,5,120,150, 2,5,max,160,

		3,7,max,100, 3,7,120,80,
		3,9,max,170, 3,9,120,150,
		3,11,120,250,
		3,5,120,135, 3,5,max,160,

		5,3,120,140, 5,3,max,160,
		5,7,120,270, 5,7,max,315,
		5,9,120,110, 5,9,max,130,
		5,11,120,130,
		7,14,300,0, 9,14,400,0, 11,14,100,0,
	};*/

	int shuru[] = { 1,3,max,210, 1,3,120,185,
		1,7,max,210, 1,7,120,200,
		1,9,max,500, 1,9,120,410,
		1,11,120,620,
		1,5,max,470, 1,5,120,400,

		0,1,500,0, 0,2,300,0,
		2,3,max,230, 2,3,120,205,
		2,7,max,210, 2,7,120,200,
		2,9,max,280, 2,9,120,240,
		2,11,120,350,
		2,5,120,150, 2,5,max,160,

		4,7,max,100, 4,7,120,80,
		4,9,max,170, 4,9,120,150,
		4,11,120,250,
		4,5,120,135, 4,5,max,160,

		6,3,120,140, 6,3,max,160,
		6,7,120,270, 6,7,max,315,
		6,9,120,110, 6,9,max,130,
		6,11,120,130,

		7,14,300,0, 9,14,400,0, 11,14,100,0,

		3,4,100,0, 5,6,80,0
	};

	int i = 0;
	while (m--)
	{
		u = shuru[i];
		i = i + 1;
		v = shuru[i];
		i = i + 1;
		c = shuru[i];
		i = i + 1;
		w = shuru[i];
		i = i + 1;
		addedge(u, v, c, w);
	}

	MCMF();
	cout << endl;
	cout << "最大流为:" << maxFlow << endl;
	cout << "最小费用为" << minCost << endl;
	cout << endl;

	system("pause");
	return 0;

}

大多数最小费用最大流的代码注释都很少,我初学的时候反正是真的看不太懂。等期末考试完了,有时间的话我再来认真写写注释,也算是记录学习过程吧~

猜你喜欢

转载自blog.csdn.net/Chelsea_n/article/details/106376362