线性规划--最大网络流

醉酒当歌 提交于 2020-01-24 17:44:31
假期 2020.01.24

### 题目描述
在这里插入图片描述
在这里插入图片描述


问题分析(内容摘自离散数学结构)

在这里插入图片描述


算法分析(内容摘自离散数学结构)

其实该问题是离散数学中了解到的最大网络流问题,借助最短增广路算法即可解决该问题。
而最短增广路算法实现是:
在这里插入图片描述
在这里插入图片描述在这里插入图片描述


代码解析

#include<iostream>
#include<algorithm>
#include<iomanip>
#include<queue>
using namespace std;
constexpr auto Max_size = 0x7fffffff;
int point_count, edge_count;//节点数,边数
int left_map[100][100];//实邻接关系
int ok_map[100][100];//虚邻接关系
int pre_map[100];//前驱
int visited[100];//访问数组
int Search_current();//寻找路径
int best_ability();//寻找最优路径
int main()
{
	int i, j,v,w,flow;
	cout << "请输入节点个数与网络连接边数:";
	cin >> point_count >> edge_count;
	cout << "请输入邻接关系与网络流:" << endl;
	memset(left_map, 0, sizeof(left_map));//初始化
	memset(ok_map, 0, sizeof(ok_map));
	for (i = 1; i <= edge_count; i++) {
		cin >> v >> w >> flow;
		left_map[v][w] = flow;
	}
	cout << "最大网络流是:" << best_ability() << endl;
	cout << "最优方案如下所示:" << endl;
	for (i = 1; i <= point_count; i++)
		cout << setw(5) << "v" << i;
	cout << endl;
	for (i = 1; i <= point_count; i++)
	{
		cout << "v" << i;
		for (j = 1; j <= point_count; j++)
			cout << setw(5) << ok_map[i][j] << " ";
		cout << endl;
	}
	return 0;
}
int best_ability()
{
	int k, maxflow = 0,temp,now_current;
	while (Search_current()){//存在路径时
		temp = point_count;
		now_current = Max_size;
		while (temp != 1){
			k = pre_map[temp];//获得前驱
			if (now_current > left_map[k][temp])//寻找当前路径中的最小流
				now_current = left_map[k][temp];
			temp = k;//向前搜索
		}
		maxflow += now_current;//最大流增加
		temp = point_count; 
		while (temp != 1)//修改网络流
		{
			k = pre_map[temp];//前驱
			left_map[k][temp] -= now_current;//正向减少
			left_map[temp][k] += now_current;//反向增加
			if (ok_map[temp][k] > 0)
				ok_map[temp][k] -= now_current;
			else
				ok_map[k][temp] += now_current;
			temp = k;
		}
	}
	return maxflow;
}
int Search_current()
{
	memset(pre_map, -1, sizeof(pre_map));
	memset(visited, 0, sizeof(visited));
	queue<int> q;
	visited[1] = 1;
	q.push(1);//头节点放入队列
	while (!q.empty())
	{
		int here = q.front();//拿头元素
		q.pop();//出队列
		for (int i = 1; i <= point_count; i++) {
			if (visited[i] == 0 && left_map[here][i] > 0)
			{
				visited[i] = 1;
				pre_map[i] = here;
				if (i == point_count)
					return 1;//已经找到一条路径
				q.push(i);
			}
		}
	}
	return 0;
}
/*
1 2 12
1 3 10
2 4 8
3 2 2
3 5 13
4 3 5
4 6 18
5 4 6
5 6 4
*/

运行结果

在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!