网络最大流 相反的方向发回一个流 选取具有最少边数的路径

《数据结构与算法分析——C语言描述》  第九章 图论算法


最少边数,就是用广度优先。

图的表示用邻接表有几个地方不是很好,删除一条边的时候,和查找一条边的时候。都是单链表的问题,所以路径直接保存了指针。


#include"hash.h"
#include"graph.h"
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<stack>
#include"fatal.h"
#include<queue>
#define MAXN 10000
using namespace std;
char nameRecord[MAXN][100];
int vexNum = 0;//点的个数计数器


Graph readGraph() {
	HashTable hash_StrToNum = initializeTable_hash(5);//初始化一个哈希表
	Graph g = initialize_Graph(5);//初始化一个邻接图

	char i_name[100];
	char j_name[100];
	int i, j;//点i,点
	double weight;//权
	while (scanf("%s%s%lf", i_name, j_name, &weight) == 3) {//输入两个点的名字,和他们之间的权,成功读入的话进入循环
		if (!isExist(i_name, hash_StrToNum)) {//查看曾经是否输入了点i,在O(1)内迅速找出
											  //点i第一次出现
			i = vexNum;//给点i分配图的下标
			strcpy(nameRecord[vexNum], i_name);//复制到名字记录中
			hash_StrToNum = insert_hash(i_name, vexNum, hash_StrToNum);//插入到哈希表中,O(1)完成
			vexNum++;//计数器增加
		}
		else {
			//以前出现过点i
			i = map_hash(i_name, hash_StrToNum);//O(1)内迅速获取点i的下标
		}
		if (!isExist(j_name, hash_StrToNum)) {
			j = vexNum;
			strcpy(nameRecord[vexNum], j_name);
			hash_StrToNum = insert_hash(j_name, vexNum, hash_StrToNum);
			vexNum++;
		}
		else {
			j = map_hash(j_name, hash_StrToNum);
		}
		insertEdge(i, j, weight, g);//在图中插入边
	}
	destroyTable_hash(hash_StrToNum);
	return g;//返回图
}

void printGraph(Graph g) {
	if (g) {
		for (int i = 0; i < vexNum; i++) {//给所有点来一个遍历
			EdgeNodePtr p = getEdgeNodePtr(i, g);//获取邻接的点
			if (p) {
				printf("%s indegree:%d ", nameRecord[i], indegree(i, g));
				for (; p; p = advance(p)) {
					if (getWeight(p) == 0)
						continue;
					printf("(%s,%s)%g ", nameRecord[i], nameRecord[getVex(p)], getWeight(p));

				}
				printf("\n");
			}
		}
	}
	else {
		Error("EMPTY GRAPH");
	}
}

Vertex startVex, endVex;//起点,终点

typedef stack<EdgeNodePtr> Path;

double minOne;

double maxFlow(Vertex srcVex, Graph g) {
	Vertex v, w;

	int *visited = (int *)malloc(sizeof(int)*vexNum);
	if (visited == NULL)
		Error("OUT OF MEMORY");
	for (int i = 0; i < vexNum; i++)
		visited[i] = 0;

	std::queue < pair<Path, double> > q;

	for (EdgeNodePtr ptr = getEdgeNodePtr(srcVex, g); ptr; ptr = advance(ptr)) {
		if (getWeight(ptr) == 0)
			continue;
		Path path;
		path.push(ptr);
		q.push({ path,getWeight(ptr) });

	}

	int find = 0;
	while (!q.empty()) {
		auto path_min = q.front();
		q.pop();
		v = getVex(path_min.first.top());
		double minWeight = path_min.second;


		if (visited[v] == 0) {
			visited[v] = 1;

			EdgeNodePtr p = getEdgeNodePtr(v, g);
			while (p) {
				w = getVex(p);
				if (getWeight(p) < minWeight)
					minWeight = getWeight(p);
				path_min.first.push(p);
				path_min.second = minWeight;
				q.push(path_min);
				if (w == endVex) {
					find = 1;
					break;
				}
				p = advance(p);
			}
		}
		if (find == 1)
			break;
	}

	if (find == 0)
		return 0;
	auto path_min = q.back();//取刚刚break;
	double min = path_min.second;
	auto & s = path_min.first;
	while (!s.empty()) {
		EdgeNodePtr p = s.top();
		s.pop();
		setWeight(getWeight(p) - min, p);
		if (!s.empty())
			insertEdge(getVex(p), getVex(s.top()), min, g);
		else
			insertEdge(getVex(p), startVex, min, g);
	}
	minOne = min;
	return 1;
}

int main() {
	freopen("filein.txt", "r", stdin);
	Graph g = readGraph();


	for (int i = 0, tag1 = 1, tag2 = 1; (tag1 || tag2) && i < vexNum; i++) {
		if (tag1&&indegree(i, g) == 0) {
			startVex = i;
			tag1 = 0;
		}
		if (tag2 && getEdgeNodePtr(i, g) == NULL) {
			endVex = i;
			tag2 = 0;
		}
	}

	double sum = 0;
	while (maxFlow(startVex, g)) {
		sum += minOne;

	}

	printf("Maximum Flow:%g\n", sum);
	printGraph(g);
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值