07-图6 旅游规划

有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。

输入格式:

输入说明:输入数据的第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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值