pat——Trave Plan

1030 Travel Plan (30 分)

A traveler's map gives the distances between cities along the highways, together with the cost of each highway. Now you are supposed to write a program to help a traveler to decide the shortest path between his/her starting city and the destination. If such a shortest path is not unique, you are supposed to output the one with the minimum cost, which is guaranteed to be unique.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 4 positive integers N, M, S, and D, where N (≤500) is the number of cities (and hence the cities are numbered from 0 to N−1); M is the number of highways; S and D are the starting and the destination cities, respectively. Then M lines follow, each provides the information of a highway, in the format:

City1 City2 Distance Cost

where the numbers are all integers no more than 500, and are separated by a space.

Output Specification:

For each test case, print in one line the cities along the shortest path from the starting point to the destination, followed by the total distance and the total cost of the path. The numbers must be separated by a space and there must be no extra space at the end of output.

Sample Input:

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

Sample Output:

0 2 3 3 40

 

题目意思是:给你n个城市,M条道路,每条道路的长度已知,每条道路上的花费也已知,让你求最短路径的长路并且输出此最短路径,如果最短路径有多条这输出花费最小的那条最短路径。

题目思路:因为本题只有两个标尺,因此可以直接用dijkstra算法一遍通过,也可以用dijkstra+dfs进行求解,与上一个博客中的题目Emergency  https://blog.csdn.net/qq_38938670/article/details/83448275   的不同之处在于此题要求打印最短路径,这就需要用的pre[]数组进行记录,如果是dijkstra算法就直接进行记录,最后直接用dfs递归求解即可打印出最短路径。但如果是dijkstra+dfs算法就是先用dijkstra算法求出所有的最短路径,此时pre[]数组要用vector<int> pre[maxv]进行存储,接着再遍历所有的最短路径,根据第二标尺进行判断,得到题目需要的路径,最后直接for循环打印路径即可,下面是这道题的两种解法的ac代码:

 

//dijkstra一遍通过代码



#include <iostream>
using namespace std;
#define inf 100000000
#define maxv 510
int n,m,st,ed;
int G[maxv][maxv];
int vis[maxv]={false};
int cost[maxv][maxv];
int c[maxv];//更新边权
int pre[maxv];//记录前驱结点
int d[maxv];//记录最短路径的长度


void Dijk(int s)
{
    fill(d,d+maxv,inf);
    fill(c,c+maxv,inf);
    d[s]=0;
    c[s]=0;
    for(int i=0;i<n;i++)
        pre[i]=i;
    for(int i=0;i<n;i++)
    {
        int u=-1,mina=inf;
        for(int j=0;j<n;j++)
        {
            if(vis[j]==false&&d[j]<mina)
            {
                mina=d[j];
                u=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])
                {
                    if(c[u]+cost[u][v]<c[v])
                    {
                        c[v]=c[u]+cost[u][v];
                        pre[v]=u;
                    }
                }
            }
        }
    }

}

void DFS(int v)
{
    if(v==st)
    {
        cout<<v<<" ";
        return;
    }
    DFS(pre[v]);
    cout<<v<<" ";
}

int main()
{
    cin>>n>>m>>st>>ed;
    int u,v;
    fill(G[0],G[0]+maxv*maxv,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];
    }
    Dijk(st);
    DFS(ed);
    cout<<d[ed]<<" "<<c[ed]<<endl;
    return 0;
}
//dijkstra + dfs代码


#include <iostream>
#include <vector>
#define maxv 510
#define inf 100000000
using namespace std;
int G[maxv][maxv];
int vis[maxv]={false};
int cost[maxv][maxv];
int d[maxv];
vector<int> pre[maxv];
vector<int> tempath,path;
int mincost=inf,n,m,st,ed;


void Dijk(int s)
{
    fill(d,d+maxv,inf);
    //fill(c,c+maxv,inf);//这种算法里面不需要用c[]数组来记录边权,可以直接求出最小的花费 
                             //mincost ,请看详细代码
    d[s]=0;
    for(int i=0;i<n;i++)
    {
        int u=-1,mina=inf;
        for(int j=0;j<n;j++)
        {
            if(vis[j]==false&&d[j]<mina)
            {
                u=j;
                mina=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].clear();
                    pre[v].push_back(u);
                }
                else if(d[u]+G[u][v]==d[v])
                {
                    //if(c[v]>c[u]+cost[u][v])
                    //{
                       // c[v]=c[u]+cost[u][v];
                        pre[v].push_back(u);
                   // }
                }
            }
        }
    }
}

void DFS(int v)
{
    if(v==st)
    {
        tempath.push_back(v);
        int value=0;
        for(int i=tempath.size()-1;i>0;i--)
        {
            int id=tempath[i],nextid=tempath[i-1];
            value=value+cost[id][nextid];
        }
        if(value<mincost)
        {
            mincost=value;
            path=tempath;
        }
        tempath.pop_back();
        return;
    }
    tempath.push_back(v);
    for(int i=0;i<pre[v].size();i++)
    {
        DFS(pre[v][i]);
    }
    tempath.pop_back();
}

int main()
{
    int u,v;
    fill(G[0],G[0]+maxv*maxv,inf);
    fill(cost[0],cost[0]+maxv*maxv,inf);
    cin>>n>>m>>st>>ed;
    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];
    }
    Dijk(st);
    DFS(ed);

    for(int i=path.size()-1;i>=0;i--)
    {
        cout<<path[i]<<" ";
    }
    cout<<d[ed]<<" "<<mincost<<endl;
    return 0;
}

读者可以尝试把这两段代码用邻接表的写法打出来,以便于理解dijkstra算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.无名之辈

1毛也是爱~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值