题目:无向图中,求图中从src节点到dest节点的最短路径,若最短路径相同,则求最少代价的路径
–对于图的算法还不是很熟悉,这道题目当做参考–
参考代码一:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int const MaxVertexNum = 500;
#define INFINITY 65535
#define Vertex int
#define WeightType int
//***********边的定义*************//
struct Enode{
Vertex V1,V2;
WeightType Weight;
WeightType Money;
};
typedef Enode *Edge;
//*************图节点定义************//
struct Gnode{
int Nv;//顶点数
int Ne;//边数
WeightType G[MaxVertexNum][MaxVertexNum]; //用了邻接矩阵
WeightType M[MaxVertexNum][MaxVertexNum];
};
typedef Gnode *MGraph;
//***************函数声明*****************//
MGraph CreateGraph(int VertexNum);
void InsertEdge(MGraph Graph, Edge E);
MGraph BuildGraph(Vertex &S, Vertex &D);
Vertex FindMinDist(MGraph Graph, int dist[],int collected[]);
bool Dijkstra(MGraph Graph, int dist[],int path[],int cost[],Vertex S);
void FindThePathOut(MGraph Graph,Vertex S,Vertex D);
int main(){
MGraph Graph;
Vertex S,D;
Graph = BuildGraph(S, D);
FindThePathOut(Graph, S, D);
return 0;
}
//*****************以下是建立图数据结构*****************//
MGraph CreateGraph(int VertexNum){
MGraph Graph;
Graph = new Gnode;
Graph->Nv = VertexNum;
Graph->Ne = 0;
for (Vertex V=0; V < Graph->Nv; ++V) {
for (Vertex W=0; W < Graph->Nv; ++W) {
Graph->G[V][W] = INFINITY;
Graph->M[V][W] = INFINITY;
}
}
return Graph;
}
void InsertEdge(MGraph Graph, Edge E){ //注意是无向图
Graph->G[E->V1][E->V2] = E->Weight;
Graph->M[E->V1][E->V2] = E->Money;
Graph->G[E->V2][E->V1] = E->Weight;
Graph->M[E->V2][E->V1] = E->Money;
}
MGraph BuildGraph(Vertex &S,Vertex &D){
MGraph Graph;
Edge E;
Vertex Nv;
cin >> Nv;
Graph = CreateGraph(Nv);
cin >> Graph->Ne >> S >> D;
if (Graph->Ne != 0) {
E = new Enode;
for (int i=0; i < Graph->Ne; ++i) {
cin >> E->V1 >> E->V2 >> E->Weight >> E->Money;
InsertEdge(Graph, E);
}
}
return Graph;
}
//*********************建立图结束*******************//
//*********************以下是最短路径算法**********************//
bool Dijkstra(MGraph Graph, int dist[],int path[],int cost[],Vertex S){
int collected[Graph->Nv]; //存放已找到最短路径的节点
Vertex V;
for (V=0; V < Graph->Nv; ++V) {
dist[V] = Graph->G[S][V];
cost[V] = Graph->M[S][V];
path[V] = S;
collected[V] = false;
}
dist[S] = 0;cost[S] = 0;collected[S] = true;
while (true) {
V = FindMinDist(Graph, dist, collected); //每轮从上一轮最短的那个节点出发
if (V == -1) {
break;
}
collected[V] = true;
for (Vertex W=0; W < Graph->Nv; ++W) {
if (collected[W]==false && Graph->G[V][W] < INFINITY) {
if (Graph->G[V][W] < 0) {
return false;
}
if (dist[V] + Graph->G[V][W] < dist[W]) {
dist[W] = dist[V] + Graph->G[V][W];
path[W] = V; //path记录到达节点w的最短路径中的w的前一个节点
cost[W] = cost[V] + Graph->M[V][W];
}
else if (dist[V]+Graph->G[V][W]==dist[W] && cost[V]+Graph->M[V][W]<cost[W]){
dist[W] = dist[V] + Graph->G[V][W];
path[W] = V;
cost[W] = cost[V] + Graph->M[V][W];
}
}
}
}
return true;
}
Vertex FindMinDist(MGraph Graph,int dist[],int collected[]){
Vertex MinV=0;
int MinDist = INFINITY;
for (Vertex V=0; V < Graph->Nv; ++V) {
if (collected[V] == false && dist[V] < MinDist) {
MinDist = dist[V];
MinV = V;
}
}
if (MinDist < INFINITY) {
return MinV;
}
else{
return -1;
}
}
//********************最短路劲算法结束**********************//
void FindThePathOut(MGraph Graph,Vertex S,Vertex D){
int dist[Graph->Nv];
int path[Graph->Nv];
int cost[Graph->Nv];
Dijkstra(Graph, dist, path, cost, S); //dist是路径代价,path是成本代价
vector<Vertex> ThePath;
Vertex P = D;
ThePath.push_back(P);
while (P != S) {
ThePath.push_back(path[P]);
P = path[P];
}
for (auto it = ThePath.rbegin(); it != ThePath.rend(); ++it) {
cout << *it << ' ';
}
cout << dist[D] << ' ' << cost[D] << endl;
}
参考代码二:
链接:https://www.nowcoder.com/questionTerminal/18972bbc26f84eb7847e5f92ec0ae1c4
来源:牛客网
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=510;
const int INF=10000000;
bool vis[maxn]={false};
int n,m,start,final,G[maxn][maxn],d[maxn];
int cost[maxn][maxn],c[maxn],pre[maxn]; //cost为对应的边的花费,c记录最小花费
void Dijkstra(int s){
fill(d,d+maxn,INF);d[s]=0; //初始化d,c,pre
fill(c,c+maxn,INF);c[s]=0;
for(int i=0;i<n;i++) pre[i]=i;
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;
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];
c[v]=c[u]+cost[u][v];
pre[v]=u;
}
else if(d[u]+G[u][v]==d[v]&&c[u]+cost[u][v]<c[v]){
c[v]=c[u]+cost[u][v];
pre[v]=u;
}
}
}
}
}
void print(int v){ //打印路径
if(v==start){
cout<<v<<" ";
return;
}
print(pre[v]);
cout<<v<<" ";
}
int main(){
cin>>n>>m>>start>>final;
int u,v;
fill(G[0],G[0]+maxn*maxn,INF);
for(int i=0;i<m;i++){
cin>>u>>v;
cin>>G[u][v]>>cost[u][v];
G[v][u]=G[u][v];
cost[v][u]=cost[u][v];
}
Dijkstra(start);
print(final); //打印路径
cout<<d[final]<<" "<<c[final];
return 0;
}
评注:dijstera算法中,d[]数组和pre数组是关键