数据结构之图论算法(邻接矩阵)

本文详细介绍了图论算法的实现,包括邻接矩阵创建图、拓扑排序、无权最短路径(Dijkstra、Floyd、Bellman_Ford、SPFA)、最小生成树(Prim、Kruskal)、深度优先搜索(DFS)以及最大流问题(EK、Dinic、SAP)。每个算法都有详细的代码实现和应用场景说明。
摘要由CSDN通过智能技术生成

图论算法(邻接矩阵)

图的创建

#define INF INT_MAX
template<typename T>
class Graph
{
private:
	struct Node
	{
	//存储顶点信息
		T value;
		//存储顶点索引
		int index;
	};
	//顶点数组
	vector<Node>Vert;
	//矩阵
	vector<vector<int>>Matrix;
	//顶点数
	int vertnum;
	//边数
	int edgenum;
public:
	Graph()
	{
		this->vertnum = this->edgenum = 0;
	}
	//通过顶点信息获得对应的索引值
	pair<int, int>Locate(const T& val1, const T& val2)
	{
		int m, n;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (Vert[i].value == val1)
				m = i;
			if (Vert[i].value == val2)
				n = i;
		}
		return make_pair(m, n);
	}
	void CreateGraph()
	{
		cout << "请输入顶点数:";
		cin >> this->vertnum;
		Vert.resize(this->vertnum);
		Matrix.resize(this->vertnum);
		for (int i = 0; i < this->vertnum; i++)
		{
			cout << "请输入第" << i + 1 << "个顶点信息:";
			cin >> Vert[i].value;
			Matrix[i].resize(this->vertnum);
			for (int j = 0; j < this->vertnum; j++)
			{
				if (i == j)
					Matrix[i][j] = 0;
				else
					Matrix[i][j] = INF;
			}
		}
		cout << "请输入边数:";
		cin >> this->edgenum;
		T val1, val2;
		int distance;
		for (int i = 0; i < this->edgenum; i++)
		{
			cout << "请输入要连接的顶点:";
			cin >> val1 >> val2;
			pair<int, int>ret = Locate(val1, val2);
			cout << "请输入边长:";
			cin >> distance;
			Matrix[ret.first][ret.second] = distance;
			//若为无向图,添加下面这一条代码
			//Matrix[ret.second][ret.first] = distance;
		}
	}
	void Print()
	{
		cout << "    ";
		for (int i = 0; i < this->vertnum; i++)
			cout << setw(3)<<Vert[i].value << " ";
		cout << endl;
		for (int i = 0; i < this->vertnum; i++)
		{
			cout << setw(3) << Vert[i].value << " ";
			for (int j = 0; j < this->vertnum; j++)
			{
				if (Matrix[i][j] == INF)
					cout << setw(3) << "oo" << " ";
				else
					cout << setw(3) << Matrix[i][j] << " ";
			}
			cout << endl;
		}
	}
};

拓扑排序

打印入度为0的顶点,然后将该顶点去除,重复上述操作
在这里插入图片描述

void Tology()
	{
		cout << "拓扑排序:";
		//记录每个节点的入度
		vector<int>In;
		In.resize(this->vertnum, 0);
		for (int i = 0; i < this->vertnum; i++)
		{
			for (int j = 0; j < this->vertnum; j++)
			{
				if (Matrix[i][j] != 0 && Matrix[i][j] != INF)
					In[j]++;
			}
		}
		//队列
		queue<int>q;
		for (int i = 0; i < this->vertnum; i++)
		{
		//入度为0,则入队列
			if (In[i] == 0)
			{
				q.push(i);
				cout << Vert[i].value << " ";
				break;
			}
		}
		while (!q.empty())
		{
			int top = q.front();
			q.pop();
			//更新各个顶点的入度
			for (int i = 0; i < this->vertnum; i++)
			{
				if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
				{
					In[i]--;
					if (In[i] == 0)
					{
						cout << Vert[i].value << " ";
						q.push(i);
					}
				}
			}
		}
		cout << endl;
	}

无权最短路径

使用DFS算法,不考虑边长,获得各个顶点到起点的距离
在这里插入图片描述

//打印路径
void print_path(vector<int>& pre, int x)
	{
		if (x == pre[x])
		{
			cout << Vert[x].value << " -> ";
			return;
		}
		print_path(pre, pre[x]);
		cout << Vert[x].value << " -> ";
	}
	void NoWeight()
	{
		cout << "请输入起点:";
		T start;
		cin >> start;
		//记录距离的数组
		vector<int>dist;
		//用于判断是否已入队
		vector<int>visit;
		vector<int>pre;
		dist.resize(this->vertnum, -1);
		visit.resize(this->vertnum, 0);
		pre.resize(this->vertnum);
		for (int i = 0; i < this->vertnum; i++)
			pre[i] = i;
		queue<int>q;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (Vert[i].value == start)
			{
				dist[i] = 0;
				visit[i] = 1;
				q.push(i);
				break;
			}
		}
		while (!q.empty())
		{
			int top = q.front();
			q.pop();
			for (int i = 0; i < this->vertnum; i++)
			{
				if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
				{
				//更新dist数组
					if (visit[i] == 0)
					{
						dist[i] = dist[top] + 1;
						visit[i] = 1;
						pre[i] = top;
						q.push(i);
					}
				}
			}
		}
		for (int i = 0; i < this->vertnum; i++)
		{
			cout << Vert[i].value << " " << dist[i] << " ";
			print_path(pre,i);
			cout << "end"<<endl;
		}
	}

Dijkstra算法

在这里插入图片描述
具体理论可看以下链接:
Dijkstra算法原理(转自平凡的L同学)

void Dijkstra()
	{
		T start;
		cout << "请输入起点:";
		cin >> start;
		vector<int>dist;
		vector<int>visit;
		vector<int>pre;
		dist.resize(this->vertnum, INF);
		visit.resize(this->vertnum, 0);
		pre.resize(this->vertnum);
		for (int i = 0; i < this->vertnum; i++)
			pre[i] = i;
		queue<int>q;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (Vert[i].value == start)
			{
				dist[i] = 0;
				visit[i] = 1;
				q.push(i);
				break;
			}
		}
		while (!q.empty())
		{
			int top = q.front();
			q.pop();
			for (int i = 0; i < this->vertnum; i++)
			{
				if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
				{
				//更新dist数组
					if (dist[top] + Matrix[top][i] < dist[i])
					{
						dist[i] = dist[top] + Matrix[top][i];
						pre[i] = top;
						//判断是否入队
						if (visit[i] == 0)
						{
							visit[i] = 1;
							q.push(i);
						}
					}
				}
			}
		}
		for (int i = 0; i < this->vertnum; i++)
		{
			cout << Vert[i].value << " " << dist[i] << " ";
			print_path(pre, i);
			cout << "end" << endl;
		}
	}

Floyd算法

获得每个顶点到其他顶点的距离
最短路径模板+解析(Floyd算法)(转自coderyzh)

void Floyd()
	{
		vector<vector<int>>capacity;
		capacity.resize(this->vertnum);
		for (int i = 0; i < this->vertnum; i++)
		{
			capacity[i].resize(this->vertnum);
			for (int j = 0; j < this->vertnum; j++)
				capacity[i][j] = Matrix[i][j];
		}
		//判断是否存在从i到k再从k到j的路径,使capacity[i][j]变小
		for (int k = 0; k < this->vertnum; k++)
		{
			for (int i = 0; i < this->vertnum; i++)
			{
				for (int j = 0; j < this->vertnum; j++)
				{
					if (capacity[i][k] != INF && capacity[k][j] != INF && capacity[i][k] + capacity[k][j] < capacity[i][j])
					{
						capacity[i][j] = capacity[i][k] + capacity[k][j];
					}
				}
			}
		}
		cout << "    ";
		for (int i = 0; i < this->vertnum; i++)
			cout << setw(3) << Vert[i].value << " ";
		cout << endl;
		for (int i = 0; i < this->vertnum; i++)
		{
			cout << setw(3) << Vert[i].value << " ";
			for (int j = 0; j < this->vertnum; j++)
			{
				if (capacity[i][j] == INF)
					cout << setw(3) << "oo" << " ";
				else
					cout << setw(3) <<capacity[i][j] << " ";
			}
			cout << endl;
		}
	}

Bellman_Ford算法

获得存在负值边的图的最短路径
图算法:2、计算带有负权值的单源最短路径:Bellman-Ford算法(转自天地一扁舟)
在这里插入图片描述
在这里插入图片描述
第一个图有负回路,第二个图无负回路

void Bellman_Ford()
	{
		vector<int>dist;
		vector<int>pre;
		dist.resize(this->vertnum, INF);
		pre.resize(this->vertnum);
		for (int i = 0; i < this->vertnum; i++)
			pre[i] = i;
		T start;
		cout << "请输入起点:";
		cin >> start;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (Vert[i].value == start)
			{
				dist[i] = 0;
				break;
			}
		}
		//松弛操作
		for (int k = 0; k < this->vertnum - 1; k++)
		{
			for (int i = 0; i < this->vertnum; i++)
			{
				for (int j = 0; j < this->vertnum; j++)
				{
					if (Matrix[i][j] != 0 && Matrix[i][j] != INF && dist[i] != INF)
					{
						if (dist[i] + Matrix[i][j] < dist[j])
						{
							pre[j] = i;
							dist[j] = dist[i] + Matrix[i][j];
						}
					}
				}
			}
		}
		bool flag = false;
		//松弛操作后,若还能松弛,则说明肯定存在负回路
		for (int i = 0; i < this->vertnum; i++)
		{
			for (int j = 0; j < this->vertnum; j++)
			{
				if (Matrix[i][j] != 0 && Matrix[i][j] != INF && dist[i] != INF)
				{
					if (dist[i] + Matrix[i][j] < dist[j])
					{
						flag = true;
						break;
					}
				}
			}
			if (flag)
				break;
		}
		if (flag)
			cout << "存在负环路" << endl;
		else
		{
			for (int i = 0; i < this->vertnum; i++)
			{
				cout << Vert[i].value << " " << dist[i] << " ";
				print_path(pre, i);
				cout << "end" << endl;
			}
		}
	}

SPFA算法

获得存在负值边的图的最短路径,与Bellman_Ford算法类似,但使用队列对Bellman_Ford进行改进
最短路径问题—SPFA算法详解(转自Ouyang_Lianjun

void SPFA()
	{
		vector<int>dist;
		vector<int>pre;
		//记录入队次数
		vector<int>count;
		dist.resize(this->vertnum, INF);
		pre.resize(this->vertnum);
		count.resize(this->vertnum, 0);
		for (int i = 0; i < this->vertnum; i++)
			pre[i] = i;
		T start;
		cout << "请输入起点:";
		cin >> start;
		queue<int>q;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (Vert[i].value == start)
			{
				dist[i] = 0;
				count[i]++;
				q.push(i);
				break;
			}
		}
		bool flag = false;
		while (!q.empty())
		{
			int top = q.front();
			q.pop();
			for (int i = 0; i < this->vertnum; i++)
			{
				if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
				{
					if (dist[top] + Matrix[top][i] < dist[i])
					{
						dist[i] = dist[top] + Matrix[top][i];
						pre[i] = top;
						count[i]++;
						q.push(i);
						//入队次数等于顶点数时,说明存在负回路
						if (count[i] == this->vertnum)
						{
							flag = true;
							break;
						}
					}
				}
			}
			if (flag)
				break;
		}
		if (flag)
			cout << "存在负环路" << endl;
		else
		{
			for (int i = 0; i < this->vertnum; i++)
			{
				cout << Vert[i].value << " " << dist[i] << " ";
				print_path(pre, i);
				cout << "end" << endl;
			}
		}
	}

Prim算法

生成最小树的一种方法
最小生成树Prim算法理解(转自qwurey)

void Prim()
	{
		T start;
		cout << "请输入起点:";
		cin >> start;
		vector<int>dist;
		vector<int>pre;
		dist.resize(this->vertnum, INF);
		pre.resize(this->vertnum);
		for (int i = 0; i < this->vertnum; i++)
			pre[i] = i;
		int top = 0;
		int count = 0;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (Vert[i].value == start)
			{
				dist[i] = -1;
				top = i;
				count++;
				break;
			}
		}
		int ans = 0;
		while (count < this->vertnum)
		{
			for (int i = 0; i < this->vertnum; i++)
			{
				if (dist[i]!=-1&&Matrix[top][i] != 0 && Matrix[top][i] != INF)
				{
					if (Matrix[top][i] < dist[i])
					{
						dist[i] = Matrix[top][i];
						pre[i] = top;
					}
				}
			}
			int minz = INF;
			int nextpos;
			for (int i = 0; i < this->vertnum; i++)
			{
				if (dist[i] != -1 && dist[i] < minz)
				{
					minz = dist[i];
					nextpos = i;
				}
			}
			if (minz == INF)
				break;
			else
			{
				cout << Vert[pre[nextpos]].value << " -- " << Vert[nextpos].value << ":" << minz << endl;
				ans += minz;
				top = nextpos;
				dist[top] = -1;
				count++;
			}
		}
		cout << ans << endl;
	}

Kruskal算法

生成最小树的一种方法,运用到并查集的知识
最小生成树(kruskal算法)(转自Superb_Day

//并查集查找和合并操作
int Find(vector<int>& pre, int x)
	{
		if (x == pre[x])
			return x;
		int root = x;
		while (root != pre[root])
			root = pre[root];
		int j = x;
		while (j != root)
		{
			int k = pre[j];
			pre[j] = root;
			j = k;
		}
		return root;
	}
	bool Union(vector<int>& pre, int root1, int root2)
	{
		root1 = Find(pre, root1);
		root2 = Find(pre, root2);
		if (root1 == root2)
			return  false;
		pre[root1] = root2;
		return true;
	}
	void Kruskal()
	{
		struct node
		{
			int from;
			int to;
			int distance;
		};
		//定义排序方式
		struct cmp
		{
			bool operator()(node a, node b)
			{
				return a.distance > b.distance;
			}
		};
		//优先队列,根据距离排序,队列最前面的是距离最小的
		priority_queue<node, vector<node>, cmp>q;
		vector<int>pre;
		pre.resize(this->vertnum);
		for (int i = 0; i < this->vertnum; i++)
		{
			pre[i] = i;
			for (int j = 0; j < this->vertnum; j++)
			{
				if (Matrix[i][j] != 0 && Matrix[i][j] != INF)
				{
					node pnew;
					pnew.from = i;
					pnew.to = j;
					pnew.distance = Matrix[i][j];
					q.push(pnew);
				}
			}
		}
		int ans = 0;
		while (!q.empty())
		{
			node top = q.top();
			q.pop();
			if (Union(pre, top.from, top.to))
			{
				ans += top.distance;
				cout << Vert[top.from].value << " -- " << Vert[top.to].value << ":" << top.distance << endl;
			}
			bool flag = false;
			for (int i = 1; i < this->vertnum; i++)
			{
			//判断是否有不再同一个集合的顶点,有的话继续进行合并
				if (Find(pre, i) != Find(pre, 0))
				{
					flag = true;
				}
			}
			if (!flag)
				break;
		}
		cout << ans << endl;
	}

DFS

图的深度搜索算法
图的广度优先搜索(BFS)和深度优先搜索(DFS)算法解析(转自Chida15)

void DFS()
	{
		T start;
		cout << "请输入起点:";
		cin >> start;
		vector<int>visit;
		visit.resize(this->vertnum, 0);
		stack<int>s;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (Vert[i].value == start)
			{
				visit[i] = 1;
				s.push(i);
				cout << Vert[i].value << " ";
				break;
			}
		}
		while (!s.empty())
		{
			int top = s.top();
			for (int i = 0; i < this->vertnum; i++)
			{
				if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
				{
				//判断是否已入队
					if (visit[i] == 0)
					{
						s.push(i);
						visit[i] = 1;
						cout << Vert[i].value << " ";
						break;
					}
				}
			}
			if (top == s.top())
				s.pop();
		}
		cout << endl;
	}

最大流之EK算法

求最大流的两种算法 EK算法和dinic算法(转自一枚研究生er)

//广度优先算法,先判断是否存在从起点到终点的路径
int bfs(vector<vector<int>>& capacity, vector<int>& pre, vector<int>& flow, int start, int end)
	{
		for (int i = 0; i < this->vertnum; i++)
		{
			pre[i] = -1;
			flow[i] = INF;
		}
		pre[start] = start;
		queue<int>q;
		q.push(start);
		while (!q.empty())
		{
			int top = q.front();
			q.pop();
			if (top == end)
				break;
			for (int i = 0; i < this->vertnum; i++)
			{
				if (pre[i]==-1&&capacity[top][i] != 0 && capacity[top][i] != INF)
				{
				//更新流的长度
					flow[i] = min(flow[top], capacity[top][i]);
					pre[i] = top;
					q.push(i);
				}
			}
		}
		if (pre[end] == -1)
			return -1;
		return flow[end];
	}
	void EK()
	{
		vector<vector<int>>capacity;
		vector<int>pre;
		vector<int>flow;
		capacity.resize(this->vertnum);
		pre.resize(this->vertnum);
		flow.resize(this->vertnum, INF);
		for (int i = 0; i < this->vertnum; i++)
		{
			pre[i] = i;
			capacity[i].resize(this->vertnum);
			for (int j = 0; j < this->vertnum; j++)
			{
				capacity[i][j] = Matrix[i][j];
			}
		}
		T start, end;
		cout << "请输入起点和终点:";
		cin >> start >> end;
		pair<int, int>ret = Locate(start, end);
		int increment = 0;
		int ans = 0;
		while (1)
		{
			increment = bfs(capacity, pre, flow, ret.first, ret.second);
			if (increment == -1)
				break;
			ans += increment;
			int k = ret.second;
			while (k != ret.first)
			{
				capacity[pre[k]][k] -= increment;
				capacity[k][pre[k]] += increment;
				k = pre[k];
			}
		}
		cout << ans << endl;
	}

最大流之Dinic算法

求最大流的两种算法 EK算法和dinic算法(转自一枚研究生er)

//广度优先算法,计算每个顶点到起点的无变最短路径
bool bfs1(vector<vector<int>>& capacity, vector<int>& dist, int start, int end)
	{
		for (int i = 0; i < this->vertnum; i++)
			dist[i] = -1;
		dist[start] = 0;
		queue<int>q;
		q.push(start);
		while (!q.empty())
		{
			int top = q.front();
			q.pop();
			for (int i = 0; i < this->vertnum; i++)
			{
				if (dist[i] == -1 && capacity[top][i] != 0 && capacity[top][i] != INF)
				{
					dist[i] = dist[top] + 1;
					q.push(i);
				}
			}
		}
		if (dist[end] == -1)
			return false;
		return true;
	}
	int dfs(vector<vector<int>>& capacity, vector<int>& dist, int now, int end, int value)
	{
		if (now == end)
			return value;
		int minz = INF;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (dist[i] == dist[now] + 1 && capacity[now][i] != 0 && capacity[now][i] != INF)
			{
				if (minz = dfs(capacity, dist, i, end, min(capacity[now][i], value)))
				{
					capacity[now][i] -= minz;
					capacity[i][now] += minz;
					return minz;
				}
			}
		}
		return 0;
	}
	void Dinic()
	{
		vector<vector<int>>capacity;
		vector<int>dist;
		capacity.resize(this->vertnum);
		dist.resize(this->vertnum, -1);
		for (int i = 0; i < this->vertnum; i++)
		{
			capacity[i].resize(this->vertnum);
			for (int j = 0; j < this->vertnum; j++)
				capacity[i][j] = Matrix[i][j];
		}
		T start, end;
		cout << "请输入起点和终点:";
		cin >> start >> end;
		pair<int, int>ret = Locate(start, end);
		int ans = 0;
		while (bfs1(capacity, dist, ret.first, ret.second))
		{
			ans += dfs(capacity, dist, ret.first, ret.second, INF);
		}
		cout << ans << endl;
	}

最大流之SAP算法

SAP是对Dinic算法的改进,通过增加一个层数组,当出现断层时,直接退出
网络流最大流的sap()算法(转自shiqi_614)

void SAP()
	{
		vector<vector<int>>capacity;
		vector<int>gap;
		vector<int>dist;
		vector<int>pre;
		vector<int>flow;
		capacity.resize(this->vertnum);
		gap.resize(this->vertnum, 0);
		dist.resize(this->vertnum, -1);
		pre.resize(this->vertnum);
		flow.resize(this->vertnum, 0);
		for (int i = 0; i < this->vertnum; i++)
		{
			pre[i] = i;
			capacity[i].resize(this->vertnum);
			for (int j = 0; j < this->vertnum; j++)
				capacity[i][j] = Matrix[i][j];
		}
		T start, end;
		cout << "请输入起点和终点:";
		cin >> start >> end;
		pair<int, int>ret = Locate(start, end);
		dist[ret.second] = 0;
		queue<int>q;
		q.push(ret.second);
		gap[0]++;
		while (!q.empty())
		{
			int top = q.front();
			q.pop();
			for (int i = 0; i < this->vertnum; i++)
			{
				if (dist[i] == -1 && capacity[i][top] != 0 && capacity[i][top] != INF)
				{
					dist[i] = dist[top] + 1;
					gap[dist[i]]++;
					q.push(i);
				}
			}
		}
		if (dist[ret.first] == -1)
			return;
		int ans = 0;
		int top = ret.first;
		int i, j;
		while (dist[ret.first] < this->vertnum)
		{
			bool flag = false;
			flow[ret.first] = INF;
			for (i = 0; i < this->vertnum; i++)
			{
				if (dist[i] + 1 == dist[top] && dist[i] >= 0 && capacity[top][i] != 0 && capacity[top][i] != INF)
				{
					flag = true;
					break;
				}
			}
			if (flag)
			{
				flow[i] = min(flow[top], capacity[top][i]);
				pre[i] = top;
				top = i;
				if (top == ret.second)
				{
					ans += flow[ret.second];
					int k = ret.second;
					while (k != ret.first)
					{
						capacity[pre[k]][k] -= flow[ret.second];
						capacity[k][pre[k]] += flow[ret.second];
						k = pre[k];
					}
					top = ret.first;
					for (int i = 0; i < this->vertnum; i++)
						flow[i] = INF;
				}
			}
			else
			{
				int minz = INF;
				for (j = 0; j < this->vertnum; j++)
				{
					if (dist[j] + 1 < minz && dist[j] >= 0 && capacity[top][j] != 0 && capacity[top][j] != INF)
					{
						minz = dist[j] + 1;
					}
				}
				gap[dist[top]]--;
				if (gap[dist[top]] == 0)
					break;
				dist[top] = minz;
				gap[minz]++;
				if (top != ret.first)
					top = pre[top];
			}
		}
		cout << ans << endl;
	}
	void dfs(vector<vector<int>>& capacity, stack<int>& s, int start) {
		for (int i = 0; i < this->vertnum; i++) {
			if (capacity[start][i] != 0) {
				capacity[start][i] = capacity[i][start] = 0;
				s.push(i);
				dfs(capacity, s, i);
				break;
			}
		}
	}
	void Fleury(vector<vector<int>>& capacity, stack<int>& s, int start)
	{
		s.push(start);
		while (!s.empty()) 
		{
			bool flag = false;
			for (int i = 0; i < this->vertnum; i++) 
			{
				if (capacity[s.top()][i] != 0)
				{
					flag = true;
					break;
				}
			}
			if (flag) {
				dfs(capacity, s, s.top());
			}
			else {
				cout << Vert[s.top()].value << " ";
				s.pop();
			}
		}
	}

欧拉回路

遍历每条边,如何回到起点的为欧拉回路;
遍历每条边的为欧拉路

void dfs(vector<vector<int>>& capacity, stack<int>& s, int start) {
		for (int i = 0; i < this->vertnum; i++) {
			if (capacity[start][i] != 0) {
				capacity[start][i] = capacity[i][start] = 0;
				s.push(i);
				dfs(capacity, s, i);
				break;
			}
		}
	}
	void Fleury(vector<vector<int>>& capacity, stack<int>& s, int start)
	{
		s.push(start);
		while (!s.empty()) 
		{
			bool flag = false;
			for (int i = 0; i < this->vertnum; i++) 
			{
				if (capacity[s.top()][i] != 0)
				{
					flag = true;
					break;
				}
			}
			if (flag) {
				dfs(capacity, s, s.top());
			}
			else {
				cout << Vert[s.top()].value << " ";
				s.pop();
			}
		}
	}
	void Euler() {
		vector<vector<int>>capacity;
		vector<int>In;
		capacity.resize(this->vertnum);
		In.resize(this->vertnum, 0);
		for (int i = 0; i < this->vertnum; i++) {
			capacity[i].resize(this->vertnum, 0);
			for (int j = 0; j < this->vertnum; j++) {
				if (Matrix[i][j] != 0 && Matrix[i][j] != INF) {
					capacity[i][j] = 1;
					In[i]++;
					In[j]++;
				}
			}
		}
		int num = 0;
		for (int i = 0; i < this->vertnum; i++){
			if (In[i] % 2 == 1)
				num++;
		}
		if (num == 0 || num == 2) {
			if (num == 0)
				cout << "存在欧拉回路:" << endl;
			else
				cout << "存在欧拉路:" << endl;
			T start;
			cout << "请输入起点:";
			cin >> start;
			stack<int>s;
			for (int i = 0; i < this->vertnum; i++)
			{
				if (Vert[i].value == start)
				{
					Fleury(capacity, s, i);
					break;
				}
			}
		}
		else
			cout << "不存在欧拉路或欧拉回路" << endl;
	}```
	

总结

#include<iostream>
using namespace std;
#include<string>
#include<queue>
#include<iomanip>
#include<stack>
#define INF INT_MAX
template<typename T>
class Graph
{
private:
	struct Node
	{
		T value;
		int index;
	};
	vector<Node>Vert;
	vector<vector<int>>Matrix;
	int vertnum;
	int edgenum;
public:
	Graph()
	{
		this->vertnum = this->edgenum = 0;
	}
	pair<int, int>Locate(const T& val1, const T& val2)
	{
		int m, n;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (Vert[i].value == val1)
				m = i;
			if (Vert[i].value == val2)
				n = i;
		}
		return make_pair(m, n);
	}
	void CreateGraph()
	{
		cout << "请输入顶点数:";
		cin >> this->vertnum;
		Vert.resize(this->vertnum);
		Matrix.resize(this->vertnum);
		for (int i = 0; i < this->vertnum; i++)
		{
			cout << "请输入第" << i + 1 << "个顶点信息:";
			cin >> Vert[i].value;
			Matrix[i].resize(this->vertnum);
			for (int j = 0; j < this->vertnum; j++)
			{
				if (i == j)
					Matrix[i][j] = 0;
				else
					Matrix[i][j] = INF;
			}
		}
		cout << "请输入边数:";
		cin >> this->edgenum;
		T val1, val2;
		int distance;
		for (int i = 0; i < this->edgenum; i++)
		{
			cout << "请输入要连接的顶点:";
			cin >> val1 >> val2;
			pair<int, int>ret = Locate(val1, val2);
			cout << "请输入边长:";
			cin >> distance;
			Matrix[ret.first][ret.second] = distance;
			Matrix[ret.second][ret.first] = distance;
		}
	}
	void Print()
	{
		cout << "    ";
		for (int i = 0; i < this->vertnum; i++)
			cout << setw(3)<<Vert[i].value << " ";
		cout << endl;
		for (int i = 0; i < this->vertnum; i++)
		{
			cout << setw(3) << Vert[i].value << " ";
			for (int j = 0; j < this->vertnum; j++)
			{
				if (Matrix[i][j] == INF)
					cout << setw(3) << "oo" << " ";
				else
					cout << setw(3) << Matrix[i][j] << " ";
			}
			cout << endl;
		}
	}
	void Tology()
	{
		cout << "拓扑排序:";
		vector<int>In;
		In.resize(this->vertnum, 0);
		for (int i = 0; i < this->vertnum; i++)
		{
			for (int j = 0; j < this->vertnum; j++)
			{
				if (Matrix[i][j] != 0 && Matrix[i][j] != INF)
					In[j]++;
			}
		}
		queue<int>q;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (In[i] == 0)
			{
				q.push(i);
				cout << Vert[i].value << " ";
				break;
			}
		}
		while (!q.empty())
		{
			int top = q.front();
			q.pop();
			for (int i = 0; i < this->vertnum; i++)
			{
				if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
				{
					In[i]--;
					if (In[i] == 0)
					{
						cout << Vert[i].value << " ";
						q.push(i);
					}
				}
			}
		}
		cout << endl;
	}
	void print_path(vector<int>& pre, int x)
	{
		if (x == pre[x])
		{
			cout << Vert[x].value << " -> ";
			return;
		}
		print_path(pre, pre[x]);
		cout << Vert[x].value << " -> ";
	}
	void NoWeight()
	{
		cout << "请输入起点:";
		T start;
		cin >> start;
		vector<int>dist;
		vector<int>visit;
		vector<int>pre;
		dist.resize(this->vertnum, -1);
		visit.resize(this->vertnum, 0);
		pre.resize(this->vertnum);
		for (int i = 0; i < this->vertnum; i++)
			pre[i] = i;
		queue<int>q;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (Vert[i].value == start)
			{
				dist[i] = 0;
				visit[i] = 1;
				q.push(i);
				break;
			}
		}
		while (!q.empty())
		{
			int top = q.front();
			q.pop();
			for (int i = 0; i < this->vertnum; i++)
			{
				if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
				{
					if (visit[i] == 0)
					{
						dist[i] = dist[top] + 1;
						visit[i] = 1;
						pre[i] = top;
						q.push(i);
					}
				}
			}
		}
		for (int i = 0; i < this->vertnum; i++)
		{
			cout << Vert[i].value << " " << dist[i] << " ";
			print_path(pre,i);
			cout << "end"<<endl;
		}
	}
	void Dijkstra()
	{
		T start;
		cout << "请输入起点:";
		cin >> start;
		vector<int>dist;
		vector<int>visit;
		vector<int>pre;
		dist.resize(this->vertnum, INF);
		visit.resize(this->vertnum, 0);
		pre.resize(this->vertnum);
		for (int i = 0; i < this->vertnum; i++)
			pre[i] = i;
		queue<int>q;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (Vert[i].value == start)
			{
				dist[i] = 0;
				visit[i] = 1;
				q.push(i);
				break;
			}
		}
		while (!q.empty())
		{
			int top = q.front();
			q.pop();
			for (int i = 0; i < this->vertnum; i++)
			{
				if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
				{
					if (dist[top] + Matrix[top][i] < dist[i])
					{
						dist[i] = dist[top] + Matrix[top][i];
						pre[i] = top;
						if (visit[i] == 0)
						{
							visit[i] = 1;
							q.push(i);
						}
					}
				}
			}
		}
		for (int i = 0; i < this->vertnum; i++)
		{
			cout << Vert[i].value << " " << dist[i] << " ";
			print_path(pre, i);
			cout << "end" << endl;
		}
	}
	void Floyd()
	{
		vector<vector<int>>capacity;
		capacity.resize(this->vertnum);
		for (int i = 0; i < this->vertnum; i++)
		{
			capacity[i].resize(this->vertnum);
			for (int j = 0; j < this->vertnum; j++)
				capacity[i][j] = Matrix[i][j];
		}
		for (int k = 0; k < this->vertnum; k++)
		{
			for (int i = 0; i < this->vertnum; i++)
			{
				for (int j = 0; j < this->vertnum; j++)
				{
					if (capacity[i][k] != INF && capacity[k][j] != INF && capacity[i][k] + capacity[k][j] < capacity[i][j])
					{
						capacity[i][j] = capacity[i][k] + capacity[k][j];
					}
				}
			}
		}
		cout << "    ";
		for (int i = 0; i < this->vertnum; i++)
			cout << setw(3) << Vert[i].value << " ";
		cout << endl;
		for (int i = 0; i < this->vertnum; i++)
		{
			cout << setw(3) << Vert[i].value << " ";
			for (int j = 0; j < this->vertnum; j++)
			{
				if (capacity[i][j] == INF)
					cout << setw(3) << "oo" << " ";
				else
					cout << setw(3) <<capacity[i][j] << " ";
			}
			cout << endl;
		}
	}
	void Bellman_Ford()
	{
		vector<int>dist;
		vector<int>pre;
		dist.resize(this->vertnum, INF);
		pre.resize(this->vertnum);
		for (int i = 0; i < this->vertnum; i++)
			pre[i] = i;
		T start;
		cout << "请输入起点:";
		cin >> start;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (Vert[i].value == start)
			{
				dist[i] = 0;
				break;
			}
		}
		for (int k = 0; k < this->vertnum - 1; k++)
		{
			for (int i = 0; i < this->vertnum; i++)
			{
				for (int j = 0; j < this->vertnum; j++)
				{
					if (Matrix[i][j] != 0 && Matrix[i][j] != INF && dist[i] != INF)
					{
						if (dist[i] + Matrix[i][j] < dist[j])
						{
							pre[j] = i;
							dist[j] = dist[i] + Matrix[i][j];
						}
					}
				}
			}
		}
		bool flag = false;
		for (int i = 0; i < this->vertnum; i++)
		{
			for (int j = 0; j < this->vertnum; j++)
			{
				if (Matrix[i][j] != 0 && Matrix[i][j] != INF && dist[i] != INF)
				{
					if (dist[i] + Matrix[i][j] < dist[j])
					{
						flag = true;
						break;
					}
				}
			}
			if (flag)
				break;
		}
		if (flag)
			cout << "存在负环路" << endl;
		else
		{
			for (int i = 0; i < this->vertnum; i++)
			{
				cout << Vert[i].value << " " << dist[i] << " ";
				print_path(pre, i);
				cout << "end" << endl;
			}
		}
	}
	void SPFA()
	{
		vector<int>dist;
		vector<int>pre;
		vector<int>count;
		dist.resize(this->vertnum, INF);
		pre.resize(this->vertnum);
		count.resize(this->vertnum, 0);
		for (int i = 0; i < this->vertnum; i++)
			pre[i] = i;
		T start;
		cout << "请输入起点:";
		cin >> start;
		queue<int>q;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (Vert[i].value == start)
			{
				dist[i] = 0;
				count[i]++;
				q.push(i);
				break;
			}
		}
		bool flag = false;
		while (!q.empty())
		{
			int top = q.front();
			q.pop();
			for (int i = 0; i < this->vertnum; i++)
			{
				if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
				{
					if (dist[top] + Matrix[top][i] < dist[i])
					{
						dist[i] = dist[top] + Matrix[top][i];
						pre[i] = top;
						count[i]++;
						q.push(i);
						if (count[i] == this->vertnum)
						{
							flag = true;
							break;
						}
					}
				}
			}
			if (flag)
				break;
		}
		if (flag)
			cout << "存在负环路" << endl;
		else
		{
			for (int i = 0; i < this->vertnum; i++)
			{
				cout << Vert[i].value << " " << dist[i] << " ";
				print_path(pre, i);
				cout << "end" << endl;
			}
		}
	}
	void Prim()
	{
		T start;
		cout << "请输入起点:";
		cin >> start;
		vector<int>dist;
		vector<int>pre;
		dist.resize(this->vertnum, INF);
		pre.resize(this->vertnum);
		for (int i = 0; i < this->vertnum; i++)
			pre[i] = i;
		int top = 0;
		int count = 0;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (Vert[i].value == start)
			{
				dist[i] = -1;
				top = i;
				count++;
				break;
			}
		}
		int ans = 0;
		while (count < this->vertnum)
		{
			for (int i = 0; i < this->vertnum; i++)
			{
				if (dist[i]!=-1&&Matrix[top][i] != 0 && Matrix[top][i] != INF)
				{
					if (Matrix[top][i] < dist[i])
					{
						dist[i] = Matrix[top][i];
						pre[i] = top;
					}
				}
			}
			int minz = INF;
			int nextpos;
			for (int i = 0; i < this->vertnum; i++)
			{
				if (dist[i] != -1 && dist[i] < minz)
				{
					minz = dist[i];
					nextpos = i;
				}
			}
			if (minz == INF)
				break;
			else
			{
				cout << Vert[pre[nextpos]].value << " -- " << Vert[nextpos].value << ":" << minz << endl;
				ans += minz;
				top = nextpos;
				dist[top] = -1;
				count++;
			}
		}
		cout << ans << endl;
	}
	int Find(vector<int>& pre, int x)
	{
		if (x == pre[x])
			return x;
		int root = x;
		while (root != pre[root])
			root = pre[root];
		int j = x;
		while (j != root)
		{
			int k = pre[j];
			pre[j] = root;
			j = k;
		}
		return root;
	}
	bool Union(vector<int>& pre, int root1, int root2)
	{
		root1 = Find(pre, root1);
		root2 = Find(pre, root2);
		if (root1 == root2)
			return  false;
		pre[root1] = root2;
		return true;
	}
	void Kruskal()
	{
		struct node
		{
			int from;
			int to;
			int distance;
		};
		struct cmp
		{
			bool operator()(node a, node b)
			{
				return a.distance > b.distance;
			}
		};
		priority_queue<node, vector<node>, cmp>q;
		vector<int>pre;
		pre.resize(this->vertnum);
		for (int i = 0; i < this->vertnum; i++)
		{
			pre[i] = i;
			for (int j = 0; j < this->vertnum; j++)
			{
				if (Matrix[i][j] != 0 && Matrix[i][j] != INF)
				{
					node pnew;
					pnew.from = i;
					pnew.to = j;
					pnew.distance = Matrix[i][j];
					q.push(pnew);
				}
			}
		}
		int ans = 0;
		while (!q.empty())
		{
			node top = q.top();
			q.pop();
			if (Union(pre, top.from, top.to))
			{
				ans += top.distance;
				cout << Vert[top.from].value << " -- " << Vert[top.to].value << ":" << top.distance << endl;
			}
			bool flag = false;
			for (int i = 1; i < this->vertnum; i++)
			{
				if (Find(pre, i) != Find(pre, 0))
				{
					flag = true;
				}
			}
			if (!flag)
				break;
		}
		cout << ans << endl;
	}
	void DFS()
	{
		T start;
		cout << "请输入起点:";
		cin >> start;
		vector<int>visit;
		visit.resize(this->vertnum, 0);
		stack<int>s;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (Vert[i].value == start)
			{
				visit[i] = 1;
				s.push(i);
				cout << Vert[i].value << " ";
				break;
			}
		}
		while (!s.empty())
		{
			int top = s.top();
			for (int i = 0; i < this->vertnum; i++)
			{
				if (Matrix[top][i] != 0 && Matrix[top][i] != INF)
				{
					if (visit[i] == 0)
					{
						s.push(i);
						visit[i] = 1;
						cout << Vert[i].value << " ";
						break;
					}
				}
			}
			if (top == s.top())
				s.pop();
		}
		cout << endl;
	}
	int bfs(vector<vector<int>>& capacity, vector<int>& pre, vector<int>& flow, int start, int end)
	{
		for (int i = 0; i < this->vertnum; i++)
		{
			pre[i] = -1;
			flow[i] = INF;
		}
		pre[start] = start;
		queue<int>q;
		q.push(start);
		while (!q.empty())
		{
			int top = q.front();
			q.pop();
			if (top == end)
				break;
			for (int i = 0; i < this->vertnum; i++)
			{
				if (pre[i]==-1&&capacity[top][i] != 0 && capacity[top][i] != INF)
				{
					flow[i] = min(flow[top], capacity[top][i]);
					pre[i] = top;
					q.push(i);
				}
			}
		}
		if (pre[end] == -1)
			return -1;
		return flow[end];
	}
	void EK()
	{
		vector<vector<int>>capacity;
		vector<int>pre;
		vector<int>flow;
		capacity.resize(this->vertnum);
		pre.resize(this->vertnum);
		flow.resize(this->vertnum, INF);
		for (int i = 0; i < this->vertnum; i++)
		{
			pre[i] = i;
			capacity[i].resize(this->vertnum);
			for (int j = 0; j < this->vertnum; j++)
			{
				capacity[i][j] = Matrix[i][j];
			}
		}
		T start, end;
		cout << "请输入起点和终点:";
		cin >> start >> end;
		pair<int, int>ret = Locate(start, end);
		int increment = 0;
		int ans = 0;
		while (1)
		{
			increment = bfs(capacity, pre, flow, ret.first, ret.second);
			if (increment == -1)
				break;
			ans += increment;
			int k = ret.second;
			while (k != ret.first)
			{
				capacity[pre[k]][k] -= increment;
				capacity[k][pre[k]] += increment;
				k = pre[k];
			}
		}
		cout << ans << endl;
	}
	bool bfs1(vector<vector<int>>& capacity, vector<int>& dist, int start, int end)
	{
		for (int i = 0; i < this->vertnum; i++)
			dist[i] = -1;
		dist[start] = 0;
		queue<int>q;
		q.push(start);
		while (!q.empty())
		{
			int top = q.front();
			q.pop();
			for (int i = 0; i < this->vertnum; i++)
			{
				if (dist[i] == -1 && capacity[top][i] != 0 && capacity[top][i] != INF)
				{
					dist[i] = dist[top] + 1;
					q.push(i);
				}
			}
		}
		if (dist[end] == -1)
			return false;
		return true;
	}
	int dfs(vector<vector<int>>& capacity, vector<int>& dist, int now, int end, int value)
	{
		if (now == end)
			return value;
		int minz = INF;
		for (int i = 0; i < this->vertnum; i++)
		{
			if (dist[i] == dist[now] + 1 && capacity[now][i] != 0 && capacity[now][i] != INF)
			{
				if (minz = dfs(capacity, dist, i, end, min(capacity[now][i], value)))
				{
					capacity[now][i] -= minz;
					capacity[i][now] += minz;
					return minz;
				}
			}
		}
		return 0;
	}
	void Dinic()
	{
		vector<vector<int>>capacity;
		vector<int>dist;
		capacity.resize(this->vertnum);
		dist.resize(this->vertnum, -1);
		for (int i = 0; i < this->vertnum; i++)
		{
			capacity[i].resize(this->vertnum);
			for (int j = 0; j < this->vertnum; j++)
				capacity[i][j] = Matrix[i][j];
		}
		T start, end;
		cout << "请输入起点和终点:";
		cin >> start >> end;
		pair<int, int>ret = Locate(start, end);
		int ans = 0;
		while (bfs1(capacity, dist, ret.first, ret.second))
		{
			ans += dfs(capacity, dist, ret.first, ret.second, INF);
		}
		cout << ans << endl;
	}
	void SAP()
	{
		vector<vector<int>>capacity;
		vector<int>gap;
		vector<int>dist;
		vector<int>pre;
		vector<int>flow;
		capacity.resize(this->vertnum);
		gap.resize(this->vertnum, 0);
		dist.resize(this->vertnum, -1);
		pre.resize(this->vertnum);
		flow.resize(this->vertnum, 0);
		for (int i = 0; i < this->vertnum; i++)
		{
			pre[i] = i;
			capacity[i].resize(this->vertnum);
			for (int j = 0; j < this->vertnum; j++)
				capacity[i][j] = Matrix[i][j];
		}
		T start, end;
		cout << "请输入起点和终点:";
		cin >> start >> end;
		pair<int, int>ret = Locate(start, end);
		dist[ret.second] = 0;
		queue<int>q;
		q.push(ret.second);
		gap[0]++;
		while (!q.empty())
		{
			int top = q.front();
			q.pop();
			for (int i = 0; i < this->vertnum; i++)
			{
				if (dist[i] == -1 && capacity[i][top] != 0 && capacity[i][top] != INF)
				{
					dist[i] = dist[top] + 1;
					gap[dist[i]]++;
					q.push(i);
				}
			}
		}
		if (dist[ret.first] == -1)
			return;
		int ans = 0;
		int top = ret.first;
		int i, j;
		while (dist[ret.first] < this->vertnum)
		{
			bool flag = false;
			flow[ret.first] = INF;
			for (i = 0; i < this->vertnum; i++)
			{
				if (dist[i] + 1 == dist[top] && dist[i] >= 0 && capacity[top][i] != 0 && capacity[top][i] != INF)
				{
					flag = true;
					break;
				}
			}
			if (flag)
			{
				flow[i] = min(flow[top], capacity[top][i]);
				pre[i] = top;
				top = i;
				if (top == ret.second)
				{
					ans += flow[ret.second];
					int k = ret.second;
					while (k != ret.first)
					{
						capacity[pre[k]][k] -= flow[ret.second];
						capacity[k][pre[k]] += flow[ret.second];
						k = pre[k];
					}
					top = ret.first;
					for (int i = 0; i < this->vertnum; i++)
						flow[i] = INF;
				}
			}
			else
			{
				int minz = INF;
				for (j = 0; j < this->vertnum; j++)
				{
					if (dist[j] + 1 < minz && dist[j] >= 0 && capacity[top][j] != 0 && capacity[top][j] != INF)
					{
						minz = dist[j] + 1;
					}
				}
				gap[dist[top]]--;
				if (gap[dist[top]] == 0)
					break;
				dist[top] = minz;
				gap[minz]++;
				if (top != ret.first)
					top = pre[top];
			}
		}
		cout << ans << endl;
	}
	void dfs(vector<vector<int>>& capacity, stack<int>& s, int start) {
		for (int i = 0; i < this->vertnum; i++) {
			if (capacity[start][i] != 0) {
				capacity[start][i] = capacity[i][start] = 0;
				s.push(i);
				dfs(capacity, s, i);
				break;
			}
		}
	}
	void Fleury(vector<vector<int>>& capacity, stack<int>& s, int start)
	{
		s.push(start);
		while (!s.empty()) 
		{
			bool flag = false;
			for (int i = 0; i < this->vertnum; i++) 
			{
				if (capacity[s.top()][i] != 0)
				{
					flag = true;
					break;
				}
			}
			if (flag) {
				dfs(capacity, s, s.top());
			}
			else {
				cout << Vert[s.top()].value << " ";
				s.pop();
			}
		}
	}
	void Euler() {
		vector<vector<int>>capacity;
		vector<int>In;
		capacity.resize(this->vertnum);
		In.resize(this->vertnum, 0);
		for (int i = 0; i < this->vertnum; i++) {
			capacity[i].resize(this->vertnum, 0);
			for (int j = 0; j < this->vertnum; j++) {
				if (Matrix[i][j] != 0 && Matrix[i][j] != INF) {
					capacity[i][j] = 1;
					In[i]++;
					In[j]++;
				}
			}
		}
		int num = 0;
		for (int i = 0; i < this->vertnum; i++){
			if (In[i] % 2 == 1)
				num++;
		}
		if (num == 0 || num == 2) {
			if (num == 0)
				cout << "存在欧拉回路:" << endl;
			else
				cout << "存在欧拉路:" << endl;
			T start;
			cout << "请输入起点:";
			cin >> start;
			stack<int>s;
			for (int i = 0; i < this->vertnum; i++)
			{
				if (Vert[i].value == start)
				{
					Fleury(capacity, s, i);
					break;
				}
			}
		}
		else
			cout << "不存在欧拉路或欧拉回路" << endl;
	}
};
int main()
{
	Graph<int>g;
	g.CreateGraph();
	g.Print();
	//g.Tology();
	//g.NoWeight();
	//g.Dijkstra();
	//g.Floyd();
	//g.Bellman_Ford();
	//g.SPFA();
	//g.Prim();
	//g.Kruskal();
	//g.DFS();
	//g.EK();
	//g.Dinic();
	//g.SAP();
	g.Euler();
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值