图的最短路径Dijkstra
Posted xiaochi
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图的最短路径Dijkstra相关的知识,希望对你有一定的参考价值。
#include <stdio.h> #include <string.h> #include <vector> #include <queue> #include <iostream> using namespace std; const int MAXV = 1000; const int INF = 1000000000; struct Node { int v,dis; }; vector<Node> Adj[MAXV]; int n;//n为顶点数,图G使用邻接表实现,MAXV为最大顶点数(点数决定如何遍历边) int m;// 边数(决定输入什么样的图) int s;//起点 int d[MAXV];//起点到达各个点的最短路径长度 bool vis[MAXV] = {false};//标记数组,vis[i]==true表示已访问,初值均为false int pre[MAXV]={0}; //记录到某一个点的前驱 void Dijkstra(int s) { fill(d,d+MAXV,INF); d[s] = 0;//起点s到达自身的距离为0 //遍历所有的点 for(int i=0;i<n;i++) { //u为使得d[u]最小的点,MIN存放该最小的d[u] int u = -1,MIN = INF; //每一趟找一个已连通的最短路径的点出来 for(int j=0;j<n;j++) { if(vis[j] == false && d[j] < MIN) { u = j; MIN = d[j]; } } //找不到小于INF的d[u],说明剩下的顶点和起点s不连通 if(u == -1) { return; } //找到了 else { vis[u] = true;//找到则标记成已访问,每一趟可以确定一个最短点 //遍历u能到达的所有顶点v,并判断以u为中转到j的距离是否比原来的小,如果小则更新 for(int j=0;j < Adj[u].size();j++) { int v = Adj[u][j].v; //以当前最短路径的点为中转,看看是否比原来的距离小 ,如果小,则优化d[v] if(vis[v] == false && d[u] + Adj[u][j].dis < d[v]) { d[v] = d[u] + Adj[u][j].dis; //记录前驱 pre[v] = u; } } } } } //输出从起点到v的最短路径 void print(int s,int v) { if(v == s) { cout << s << endl; return; } print(s,pre[v]); cout<< v << endl; } int main() { //顶点个数,边数,起点编号 cin >> n >> m >> s; int u,v,w; Node tmp; for (int i=0;i<m;i++) { cin >> u >> v >> w; tmp.v = v; tmp.dis = w; Adj[u].push_back(tmp); } Dijkstra(s); for(int i=0;i<n;i++) { cout << d[i] << " "; } cout << endl; print(0,5); return 0; }
#include <vector> #include <string> #include <algorithm> #include <iostream> using namespace std; const int MAXV = 510; const int INF = 1000000000; //n为点数,m为边数,st和ed分别为起点和终点 //G为邻接矩阵,weight为点权 //d[]记录最短距离,w[]记录最大点权之和 int n,m,st,ed,G[MAXV][MAXV],weight[MAXV]; int d[MAXV],w[MAXV]; //vis[i] == true 表示顶点i已访问 bool vis[MAXV] = {false}; vector<int> pre[MAXV]; void Dijkstra(int s) { fill(d,d+MAXV,INF); d[s] = 0; //每次找出一个最短的点,一共找n个 ,最短的点就是在最短路径中的点,设置为访问 for(int i=0;i<n;i++) { int u = -1,MIN = INF; //找最短的点 for(int j=0;j<n;j++) { if(vis[j] == false && d[j] < MIN) { u = j; MIN = d[j]; } } if(u == -1 ) return; vis[u] = true; //看u能到哪些点 ,并以u为中转,更新其他距离 //以u为中转,到v for(int v=0;v<n;v++) { if(vis[v] == false && G[u][v] != INF) { if(d[u] + G[u][v] < d[v]) { d[v] = d[u] + G[u][v]; pre[v].clear(); //令v的前驱为u pre[v].push_back(u); } else if(d[u]+G[u][v] == d[v]) { pre[v].push_back(u); } } } } } //求最大值 int optvalue = -INF; //最优路径及临时路径 vector<int> path,tempPath; //路径数+1 int totalCount = 0; void DFS(int v) { // cout << endl; //到达叶子节点,即起点 if(v == st) { totalCount++; tempPath.push_back(v); int value = 0; for(int i=0;i<tempPath.size();i++) { // value = value + G[ tempPath[i] ][ tempPath[i+1] ]; value = value + weight[tempPath[i]]; } if(value > optvalue) { optvalue = value; path = tempPath; } //回溯 tempPath.pop_back(); return; } //将当期访问的点加入临时路径 tempPath.push_back(v); //访问所有前驱 for(int i=0;i<pre[v].size();i++) { //递归遍历所有前驱 DFS(pre[v][i]); } tempPath.pop_back(); } int main() { cin >> n >> m >> st >> ed; for(int i=0;i<n;i++) { cin >> weight[i]; } int u,v; fill(G[0],G[0] + MAXV * MAXV,INF); for(int i=0;i<m;i++) { cin >> u >> v; cin >> G[u][v]; G[v][u] = G[u][v]; } Dijkstra(st); DFS(ed); cout << totalCount << " " << optvalue << endl; return 0; }
以上是关于图的最短路径Dijkstra的主要内容,如果未能解决你的问题,请参考以下文章