PAT 数据结构 06-图5. 旅游规划dijkstra算法

题意:

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

输入:

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;
}

猜你喜欢

转载自blog.csdn.net/lanshan1111/article/details/82956405
今日推荐