图有关的题目

狄杰斯特拉算法

#include<iostream>
#include<vector>
#include<cstring>
#include<queue>
using namespace std;

const int maxn = 10000;//最大顶点数
const int inf = 1000000000;//无穷大 10的九次方
struct node
{
    
    
	int layer;
	int id;//结点编号和层号
};
vector<node>adj[maxn];//邻接表的bfs遍历


//用户输入顶点个数 边数 起点编号 单源最短路径问题 给定图G(V,E)和起点s,求出起点s到其他顶点的最短距离
int G[maxn][maxn], n,u,bian,beginn;//n:顶点数(自己设置 bian:边数 beginn:起点)图一般是全局变量
int d[maxn];//起点到各顶点的最短路径长度
bool inq[maxn] = {
    
     false };
//邻接矩阵法  该算法只能应对所有边权都是非负数的情况
void dijksra(int begin)//begin为起点
{
    
    
	
	
	fill(d, d + maxn, inf);
	d[begin] = 0;//到自身的距离为0
	for (int i = 0; i < n; i++)//循环n次
	{
    
    
		int min = inf;
		u = -1;//u使得d[u]最小 min存放最小的d[u]
		for (int j = 0; j < n; j++) {
    
    //找到未访问的顶点中d[]最小的
			if (inq[j] == false && d[j] < min)
			{
    
    
				
				u = j;
				min = d[j];
			}
		}


		if (u == -1) return;//如果u未发生变化则找不到小于inf的d[u],说明剩下的顶点和begin不连通
		
	
			inq[u] = true;//标记为已经访问过
			for (int j = 0;j < n;j++)//如果j未访问&&u可以到达j&&以u为中介点可以使得d[j]更优
			{
    
    
				if (inq[j] == false && G[u][j]!=inf && G[u][j] + d[u] < d[j])
					d[j] = G[u][j] + d[u];
			}
		}
	}



int main()
{
    
    
	int u, v, j;
	cin >> n >> bian >> beginn;//输入顶点个数 边数 起点编号(点的编号从0开始
	fill(G[0], G[0] + maxn * maxn, inf);//初始化图G一开始全都是无穷大
	for (int i = 0; i < bian; i++)
	{
    
    
		cin >> u >> v >> j;//输入点u v以及从u到v的边权
		G[u][v] = j;
	}
	dijksra(beginn);
	for (int i = 0; i < n; i++)
		cout << d[i] << " ";//输出所有顶点的最短距离

}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

`在这里插入图片描述

如果有多条最短路径:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201126154230862.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzU4NTc0,size_16,color_FFFFFF,t_70#pic_center)

![在这里插入图片描述](https://img-blog.csdnimg.cn/20201126154336852.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzU4NTc0,size_16,color_FFFFFF,t_70#pic_center)


![在这里插入图片描述](https://img-blog.csdnimg.cn/2020112615424832.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzU4NTc0,size_16,color_FFFFFF,t_70#pic_center)

## 通过vector类型的数组pre寻找最短路径
![在这里插入图片描述](https://img-blog.csdnimg.cn/20201128150421976.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQxMzU4NTc0,size_16,color_FFFFFF,t_70#pic_center)

```cpp
int st;
int optvalue;//opt为第二标尺最优值 
vector<int>path, temppath;//一条最优的路径和临时的路径
void dfs(int v)//v为当前访问的结点
{
	if (v == st)//如果到了叶子结点,即起始点
	{
		int value;//value为临时路径上的第二标尺的值
		temppath.push_back(v);//将路径起始点加入到临时路径的最后面
		//计算temmpath路径上的第二标尺value的值
		if (value > optvalue)
		{
			optvalue = value;//更新第二标尺的值和最优路径
			path = temppath;
		}
		temppath.pop_back();//删除刚刚加入的结点
		return;
	}
	//if v != st
	temppath.push_back(v);//当前访问的结点加入到临时路径temppath的后面
	for (int i = 0; i < temppath.size(); i++)
	{
		int nex = pre[v][i];//对v的前驱结点进行递归访问 前驱结点pre[v][i]
		dfs(nex);
	}
	temppath.pop_back();//遍历完所有的前驱结点 删除刚刚加入的结点
}

int value=0;//边权
	for (int i = temppath.size() - 1; i > 0; i--)
	{
    
    
		int id = temppath[i],nextid = temppath[i-1];//当前结点为id,下一个结点为nextid
		int nextint = temppath[i - 1];//循环条件为i>0
		value +=  G[id][nextid];
	//value增加从id到nextid的边权 这里G表示一个点到另一个点之间边权大小
	}
	int value = 0;//点权之和
	for (int i =  temppath.size()-1; i >= 0; i--)
	{
    
    
		int id = temppath[i];//循环条件为i>=0
		value += w[id];//value增加id的点权
	}

一条路径的边权或者点权进行计算

给出N个城市个M条道路 每条道路的花费和距离 起点和终点给定 求出最短距离,如果有多条距离最短,求最小花费的路径

#include<iostream>
#include<string>
#include<vector>
#include<Windows.h>
#include <conio.h>
#include<ctime>
#include<stack>
#include<cctype>
#include<cmath>
#include<stdio.h>
#include <windows.h>
#include<algorithm>
#include<cstring>
using namespace std;
int m_direction;
string str;



//使用狄杰特斯拉算法记录所有最短路径
const int maxn = 1000,inf=100000000;
int M, N,st,sd;//st起点 sd终点 N个城市编号为0~N-1 M条道路为无向边 给出M条道路的距离属性以及花费属性
int mincost=inf;
int d[maxn];
bool inq[maxn] = {
    
     false };
vector<int> pre[maxn];//存放结点的前驱结点
int optvalue;//opt为第二标尺最优值 
vector<int>path, temppath;//一条最优的路径和临时的路径

int distancee[maxn][maxn],dis;
int costt[maxn][maxn];//花费
void dijksra(int s)//s为起点
{
    
    
	int u;

	fill(d, d + maxn, inf);
	d[s] = 0;//到自身的距离为0

	for (int i = 0; i <N; i++)
	{
    
    
		u = -1;
		int min = inf;//注意min初始化的位置是在循环里面 每次
		for (int j = 0; j <N; j++)
		{
    
    
			if (inq[j] == false && d[j] < min)
			{
    
    
				u = j;
				min = d[j];//先找到最小的d[u] u是下标
			}
		}

		if (u == -1) return;//说明剩下的点和起始点不连通
		inq[u] = true;//标记为已经访问过
		for (int v = 0; v < N; v++)
		{
    
    
			if (inq[v] == false && distancee[u][v] != inf) {
    
    
				if (d[u] + distancee[u][v] < d[v])
				{
    
    
					d[v] = d[u] + distancee[u][v];
					pre[v].clear();
					pre[v].push_back(u);
				}
				else if (d[u] + distancee[u][v] == d[v])
					pre[v].push_back(u);
			}
		}

	}
}
void dfs(int v)//v为当前访问的结点
{
    
    
	if (v == st)//如果到了叶子结点,即起始点
	{
    
    
		int temcost = 0;//当前的花费之和
	
		temppath.push_back(v);//将路径起始点加入到临时路径的最后面
		for (int i = temppath.size() - 1; i > 0; i--)
		{
    
    
			int id = temppath[i], nextid = temppath[i - 1];//当前结点为id,下一个结点为nextid
			//循环条件为i>0
			temcost += costt[id][nextid];
			//value增加从id到nextid的边权 这里G表示一个点到另一个点之间边权大小
		}
		
		if (temcost < mincost)
		{
    
    
			mincost=temcost;//更新第二标尺的值和最优路径
			path = temppath;
		}
		temppath.pop_back();//删除刚刚加入的结点
		return;
	}
	//if v != st
	temppath.push_back(v);//当前访问的结点加入到临时路径temppath的后面
	for (int i = 0; i < pre[v].size(); i++)
	{
    
    
		int nex = pre[v][i];//对v的前驱结点进行递归访问 前驱结点pre[v][i]
	
		dfs(nex);
	}
	temppath.pop_back();//遍历完所有的前驱结点 删除刚刚加入的结点
	return;
}
//4 5 0 3
//0 1 1 20
//1 3 2 30
//0 3 4 10
//0 2 2 20
//2 3 1 20
int main()
{
    
    
	int huafei;
	int i, j;
	cin >> N >> M >> st >> sd;
	fill(distancee[0], distancee[0] + maxn * maxn, inf);
	fill(costt[0], costt[0] + maxn * maxn, inf);
	for (int z = 0;z < M; z++)
	{
    
    
		cin >> i >> j;
		cin >> distancee[i][j];
		distancee[j][i]= distancee[i][j];
		cin >> costt[i][j];
		costt[j][i] = costt[i][j];
	}

	dijksra(st);
	dfs(sd);
	for (int i = path.size()-1; i >= 0; i--)
		cout << path[i] << " ";
	cout << endl;
	cout << d[sd] << " " <<mincost;//输出最短距离和最小花费
}



猜你喜欢

转载自blog.csdn.net/qq_41358574/article/details/110188920
今日推荐