1030 Travel Plan (30分) dij模板题(双关键字)

dijkstra算法原理

题目

https://pintia.cn/problem-sets/994805342720868352/problems/994805464397627392

题意

1030旅行计划(30分)
旅行者地图给出了高速公路沿线城市之间的距离,以及每条高速公路的成本。现在你应该编写一个程序来帮助旅行者决定他/她的起始城市和目的地之间的最短路径。如果这样最短的路径不是唯一的,则应输出具有最低成本的路径,该路径保证是唯一的。

输入规格:
每个输入文件包含一个测试用例。每个事例都以包含 4 个正整数的行开头N,M,S和D哪里N (≤500) 是城市的数量(因此城市编号从 0 到N−1); M是高速公路的数量;S和D分别是起始城市和目的地城市。然后M线如下,每条提供高速公路的信息,格式为:

City1 City2 Distance Cost
其中,数字都是不超过 500 的整数,并用空格分隔。

输出规格:
对于每个测试用例,在一行中打印从起点到目的地的最短路径沿线的城市,后跟路径的总距离和总成本。数字必须用空格分隔,输出末尾不得有多余的空格。

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

邻接矩阵版
//复杂度O(n^2)
#include<bits/stdc++.h>
using namespace std;

int INF=0x3f3f3f3f;
int N,M,S,D;//城市数、道路数、起点、终点

struct node{
    int dist;//原点到该点距离(第一关键字)
    int cost;//原点到该点花费(第二关键字)
    bool flag;//是否访问过
    bool operator < (const node &a) {
        return (dist<a.dist || (dist==a.dist && cost<a.cost));
    }
}city[505];

int dist[505][505];//两点间距离
int cost[505][505];//两点间花费

int fa[505];//记录路径

void dijkstra()
{
    //初始化节点信息city[]
    for(int i=0;i<N;i++){
        city[i].dist=(i==S?0:INF);
        city[i].cost=(i==S?0:INF);
        city[i].flag=0;
    }
    int y=N;
    while(y--)//全部点被访问后才停止
    {
        //选择未访问过的最近节点k,加入集合
        int k=-1;
        node temp;
        temp.cost=INF; temp.dist=INF;
        for(int i=0;i<N;i++)
        {
            if(city[i].flag) continue;
            else if(city[i]<temp) {
                temp.cost=city[i].cost; temp.dist=city[i].dist;
                k=i;
            }
        }

        city[k].flag=1;//加入集合

        //对k点周围relax
        for(int i=0;i<N;i++)
        {
            if(dist[k][i]==0 || city[i].flag) continue;
            if(city[i].dist>city[k].dist+dist[k][i] || (city[i].dist==city[k].dist+dist[k][i] && city[i].cost>city[k].cost+cost[k][i]))
            {
                city[i].dist=city[k].dist+dist[k][i];
                city[i].cost=city[k].cost+cost[k][i];
                fa[i]=k;//最短路径中i的前驱为k
            }
        }
    }
}


int main()
{
    cin>>N>>M>>S>>D;
    int a,b,c,d;// a<--->b  距离c 花费d
    for(int i=0;i<M;i++){
        cin>>a>>b>>c>>d;
        dist[a][b]=c; cost[a][b]=d;
        dist[b][a]=c; cost[b][a]=d;
    }
    dijkstra();
    //打印路径
    stack<int>path;
    int p=D;
    while(p!=S){
        path.push(p);
        p=fa[p];
    }
    cout<<S<<" ";
    while(!path.empty()){
        cout<<path.top()<<" ";
        path.pop();
    }
    cout<<city[D].dist<<" "<<city[D].cost;
    return 0;
}


邻接表 优先队列版(屑)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int N,M,S,D;
struct node{
    int d,c,num;
}city[505];
struct edge{
    int v,d,c;
    edge(int a,int b,int c1):v(a),d(b),c(c1){}
};
vector<edge>G[505];
bool operator < (const node x,const node y) {return x.d>y.d;}
bool visit[505];
int fa[505];
void dij()
{
    for(int i=0;i<N;++i) {
        city[i].num=i;
        city[i].c=(i==S?0:INT_MAX);
        city[i].d=(i==S?0:INT_MAX);
    }
    priority_queue<node>Q;
    Q.push(city[S]);
    while(!Q.empty())
    {
        node t=Q.top(); Q.pop();
        if(visit[t.num]) continue;
        else visit[t.num]=1;

        int u=t.num;
        for(int i=0;i<G[u].size();++i)
        {
            int v=G[u][i].v;
            int dis=G[u][i].d;
            int cost=G[u][i].c;
            if(city[v].d>city[u].d+dis ||
               (city[v].d==city[u].d+dis && city[v].c>city[u].c+cost))
           {
               city[v].d=city[u].d+dis;
               city[v].c=city[u].c+cost;
               fa[v]=u;
               Q.push(city[v]);
           }
        }
    }
}

void path()
{
    stack<int>st;
    int p=D;
    while(p!=S)
    {
        st.push(p);
        p=fa[p];
    }
    cout<<S;
    while(!st.empty()){
        cout<<" "<<st.top();
        st.pop();
    }
}

int main()
{
    cin>>N>>M>>S>>D;
    for(int i=1;i<=M;++i)
    {
        int a,b,c,d; cin>>a>>b>>c>>d;
        G[a].push_back(edge(b,c,d));
        G[b].push_back(edge(a,c,d));
    }
    dij();
    path();
    cout<<" "<<city[D].d<<" "<<city[D].c<<endl;
    return 0;
}
posted @ 2020-08-17 12:10  liuyongliu  阅读(106)  评论(0编辑  收藏  举报