《数据结构与算法分析——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);
}