有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。
输入格式:
输入说明:输入数据的第1行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0~(N−1);M是高速公路的条数;S是出发地的城市编号;D是目的地的城市编号。随后的M行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。输入保证解的存在。
输出格式:
在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。
输入样例:
4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20
输出样例:
3 40
思路:
1.根据各个城市以及公路建立无向图,此处使用邻接表方式存储,注意边有两个权值;(图的邻接表形式结构定义,BuiltG函数,CreatG函数,InsertEdge函数)
2.根据读入的出发城市进行有权图的单源最短路径算法,Dijkstra算法,其中需要FindMinDist来寻找未收录顶点中的Dist最小的顶点,首先以Dist为权值寻找,当一个顶点有多条路径可以到达且Dist相等,需要更新花费Expense,取较小值。
(FindMinDist函数,可以直接遍历整个图,也可以使用最小堆)
Initial函数初始化,Dist和Expense初始为INFINTITY,当遇到更小的Dist要更新,此时再更新Expense)
#include<stdio.h>
#include<stdlib.h>
#define Vertex int
#define Length int
#define Cost int
#define MaxSize 500
#define INFINITY 65535
#define Min(a,b) a<b?a:b
typedef struct ENode *PtrToEdge;
struct ENode{
Length L;
Cost C;
};
typedef struct VNode *PtrToVNode;
struct VNode{
Vertex V;
Length L;
Cost C;
PtrToVNode Next;
};
typedef struct List{
PtrToVNode FirstEdge;
}AdjVNode[MaxSize];
typedef struct GNode *LGraph;
struct GNode{
AdjVNode G;
int Nv;
int Ne;
};
LGraph BuiltG(int N,int M);
LGraph CreatG(int N);
void InsertEdge(LGraph G,Vertex V1,Vertex V2,Length L,Cost C);
void Initial(int N);
void Dijkstra(LGraph G,Vertex S);
Vertex FindMinDist(Length Dist[],bool Collect[],int N);
Length Dist[MaxSize];
Cost Expense[MaxSize];
bool Collect[MaxSize]={};
int main()
{
LGraph G;
int N,M,S,D;
scanf("%d %d %d %d",&N,&M,&S,&D);
G=BuiltG(N,M);
Initial(N);
Dijkstra(G,S);
printf("%d %d\n",Dist[D],Expense[D]);
return 0;
}
LGraph BuiltG(int N,int M)
{
LGraph G;
int i;
PtrToEdge E;
Vertex V1,V2;
G=CreatG(N);
G->Nv=N;
G->Ne=M;
E=(PtrToEdge)malloc(sizeof(struct ENode));
for(i=0;i<M;i++)
{
scanf("%d %d %d %d",&V1,&V2,&E->L,&E->C );
InsertEdge(G,V1,V2,E->L,E->C );
}
return G;
}
LGraph CreatG(int N)
{
LGraph G=(LGraph)malloc(sizeof(struct GNode));
int V;
for(V=0;V<N;V++)
{
G->G[V].FirstEdge=NULL;
}
return G;
}
void InsertEdge(LGraph G,Vertex V1,Vertex V2,Length L,Cost C)
{
PtrToVNode NewNode;
NewNode=(PtrToVNode)malloc(sizeof(struct VNode));
NewNode->V=V2;
NewNode->L=L;
NewNode->C=C;
NewNode->Next=G->G[V1].FirstEdge;
G->G[V1].FirstEdge=NewNode;
NewNode=(PtrToVNode)malloc(sizeof(struct VNode));
NewNode->V=V1;
NewNode->L=L;
NewNode->C=C;
NewNode->Next=G->G[V2].FirstEdge;
G->G[V2].FirstEdge=NewNode;
}
void Initial(int N)
{
Vertex V;
for(V=0;V<N;V++)
{
Dist[V]=INFINITY;
Expense[V]=INFINITY;
}
}
void Dijkstra(LGraph G,Vertex S)
{
Vertex V;
PtrToVNode p;
Dist[S]=0;
Expense[S]=0;
while(1)
{
V=FindMinDist(Dist,Collect,G->Nv);//ÕÒ×îСDist
if(V==-1)
break;
Collect[V]=true;
p=G->G[V].FirstEdge;
for(;p;p=p->Next)//δÊÕ¼µÄÁÚ½Óµã
{
if(Collect[p->V]==false)
{
if(Dist[p->V]>Dist[V]+p->L )//¶Ô¸ÕÊÕ¼½áµãµÄÁÚ½ÓµãµÄDistÖµ½øÐиüУ¬Èç¹ûDistÖµ¸üеĻ° £¬ExpenseÖµÒ²½øÐиüÐÂ
{
Dist[p->V]=Dist[V]+p->L;
Expense[p->V]=Expense[V]+p->C;
}
else if(Dist[p->V]==Dist[V]+p->L )//DistÖµ²»ÐèÒª¸üУ¬ExpenseÖµÐèÒª¸üÐÂÈ¡×îС
{
Expense[p->V]=Min(Expense[p->V],Expense[V]+p->C);
}
}
}
}
}
Vertex FindMinDist(Length Dist[],bool Collect[],int N)
{
Vertex V,MinV;
Length MinDist;
MinDist=INFINITY;
for(V=0;V<N;V++)
{
if(Collect[V]==false&&Dist[V]<MinDist)
{
MinDist=Dist[V];
MinV=V;
}
}
if(MinDist!=INFINITY)
return MinV;
else
return -1;
}