题意:
有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。
输入:
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
题解:
#include<bits/stdc++.h>
using namespace std;
#define MAXN 505
#define INFINITY 505
struct City
{
int len;
int fees;
};
int N; //城市的个数 编号 0 ~ (N - 1)
int M; //高速公路的条数
int S; //出发地的城市编号
int D; //目的城市编号
City city[MAXN][MAXN]; //图
int flag[MAXN]; //标记
City dist[MAXN]; //dist表示 这个点到原点的最短路径
int Length; //路径长度
int Fees; //收费额
void init()
{
for(int i = 0; i < N; ++i)
{
for(int j = 0; j < N; ++j)
{
city[i][j].len = INFINITY;
city[i][j].fees = INFINITY;
}
}
for(int i = 0; i < N; ++i)
{
dist[i].len = INFINITY;
dist[i].fees = INFINITY;
}
}
void setDistValue(int s, int i, int j)
{
dist[S].len = i;
dist[S].fees = j;
}
int findMinDist()
{
City minDist;
minDist.fees = INFINITY;
minDist.len = INFINITY;
int V; //用于返回的顶点
for(int i = 0; i < N; ++i)
{
if(flag[i] == 0)
{//找到与之最短距离的点;
if(dist[i].len < minDist.len)
{
minDist.len = dist[i].len;
minDist.fees = dist[i].fees;
V = i;
}
else if(dist[i].len == minDist.len)
{
if(dist[i].fees < minDist.fees)
minDist.fees = dist[i].fees;
}
}
}
if(minDist.len < INFINITY)
return V; //返回对应的顶点下标
else return -1; //这样的顶点不存在,也就是所有点已经标记完
}
void dijkstra()
{
setDistValue(S, 0, 0); //将起点S吃入集合
flag[S] = 1; //标记
for(int i = 0 ; i < N; ++i)
{
dist[i].len = city[S][i].len;
dist[i].fees = city[S][i].fees;
}//初始化;
int V; //用来表示顶点下标
while(1)
{
V = findMinDist();//仔细理解一下这个点;
if(V == -1) //这样结点不存在
break;
flag[V] = 1; //吃入
for(int i = 0; i < N; ++i) //对图中的每个顶点
{
if(flag[i] == 0 && city[V][i].len < INFINITY) // W是V的邻边且未被吃入
{
if(city[V][i].len < 0) //为负边
return ; //所有点已经标记完,结束;
if(dist[V].len + city[V][i].len < dist[i].len) //吃入V使得dist[i]变小
{
dist[i].len = dist[V].len + city[V][i].len;
dist[i].fees = dist[V].fees + city[V][i].fees;
}
else if(dist[V].len + city[V][i].len == dist[i].len) //吃入V等于dist[i]
{
if(dist[V].fees + city[V][i].fees < dist[i].fees) //路费比其少则更新
dist[i].fees = dist[V].fees + city[V][i].fees;
}
}
}
}
}
int main()
{
scanf("%d%d%d%d", &N, &M, &S, &D);
init(); //初始化
int beginCity;
int endCity;
int len;
int fees;
for(int i = 0; i < M; ++i)
{
scanf("%d%d%d%d", &beginCity, &endCity, &len, &fees);
city[beginCity][endCity].len = len;
city[beginCity][endCity].fees = fees;
city[endCity][beginCity].len = len;
city[endCity][beginCity].fees = fees;
//路是双向的;
}
dijkstra();
printf("%d %d", dist[D].len, dist[D].fees);
return 0;
}