算法笔记-问题 D: 最短路径

问题 D: 最短路径

题目描述

有n个城市m条道路(n<1000, m<10000),每条道路有个长度,请找到从起点s到终点t的最短距离和经过的城市名。

输入

输入包含多组测试数据。

每组第一行输入四个数,分别为n,m,s,t。

接下来m行,每行三个数,分别为两个城市名和距离。

输出

每组输出占两行。

第一行输出起点到终点的最短距离。

第二行输出最短路径上经过的城市名,如果有多条最短路径,输出字典序最小的那条。若不存在从起点到终点的路径,则输出“can't arrive”。

样例输入 Copy

3 3 1 3
1 3 3
1 2 1
2 3 1

样例输出 Copy

2
1 2 3

代码:

#include <bits/stdc++.h>

using namespace std;

const int INF = (1)<<31-1;
const int maxn = 1010;

struct node{
    int v, w;
    node(int x, int y):v(x), w(y){};
};

int n, m, s, t;
int dist[maxn];
vector<node> Adju[maxn];
int pre[maxn];
bool visit[maxn] = {false};
vector<int> path, tempPath;

void DIJ(int s){
    fill(dist, dist+maxn, INF);
    fill(visit, visit+maxn, false);
    for(int i=1; i<=n; i++){
        pre[i] = i;
    }
    dist[s] = 0;
    for(int i=1; i<=n; i++){
        int u = -1, minx = INF;
        for(int j=1; j<=n; j++){
            if(visit[j]==false&&dist[j]<minx){
                u = j;
                minx = dist[j];
            }
        }
        if(u==-1) return;
        visit[u] = true;
        for(int v=1; v<=n; v++){
            if(visit[v]==false){
                if(dist[u]+Adju[u][v].w<dist[v]){
                    dist[v] = dist[u]+Adju[u][v].w;
                    pre[v] = u;
                }
                else if(dist[u]+Adju[u][v].w==dist[v]&&u<pre[v]){
                    pre[v] = u;
                }
            }
        }
    }
}

void DFS(int v, int s){
    if(v==s){
        printf("%d ", v);
        return;
    }
    DFS(pre[v], s);
    printf("%d ", v);
}

int main(){
    while(scanf("%d%d%d%d", &n, &m, &s, &t)!=EOF){
        for(int i=1; i<=n; i++){
            Adju[i].clear();
        }
        for(int i=0; i<m; i++){
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            Adju[u].push_back(node(v, w));
            Adju[v].push_back(node(u, w));
        }
        DIJ(s);
        if(dist[t]==INF)
            printf("can't arrive\n");
        else{
            printf("%d\n", dist[t]);
            DFS(t, s);
            printf("\n");
        }
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值