1030 Travel Plan (30 分) 题解(dijkstra+dfs)

题目传送门

解题思路:

  题目要求我们计算出从起点到终点的最短路径,所以需要使用最短路算法将最短路径算出来,此外可能会存在多条最短路径,我们需要将保存并输出花费最小的最短路径。于是我们就可以用一个数组来存储最短路径上节点的前驱节点,再利用深度优先搜索逆向遍历一边就可以得到我们的正确路径。这里我们使用邻接表来存储图。
  要注意边的个数问题,我第一次出错就在于没有开足够大的空间来存储边。

代码
#include<bits/stdc++.h>
using namespace std;

typedef pair<int,int> PII;

const int N=510*510;//这里要开大一些

int n,m,s,d;
int h[N],e[N],ne[N],w[N],c[N],idx;

void add(int a,int b,int dis,int cost)
{
    e[idx]=b;
    w[idx]=dis;
    c[idx]=cost;
    ne[idx]=h[a];
    h[a]=idx++;
}

int dist[N];
int cost[N];
bool vis[N];
vector<int> path(N);

void dijkstra()
{
    memset(dist,0x3f,sizeof dist);
    memset(cost,0x3f,sizeof cost);
    cost[s]=0;
    dist[s]=0;
    priority_queue<PII,vector<PII>,greater<PII> >heap;
    heap.push({0,s});

    while(heap.size())
    {
        auto t=heap.top();
        heap.pop();
        int v=t.second,dis=t.first;

        if(vis[v]) continue;
        vis[v]=true;
        for(int i=h[v];i!=-1;i=ne[i])
        {
            int u=e[i];
            if(dist[u]>dis+w[i])//这里是主要逻辑
            {
                dist[u]=dis+w[i];
                cost[u]=cost[v]+c[i];
                path[u]=v;
                heap.push({dist[u],u});
            }
            else if(dist[u]==dis+w[i])
            {
                if(cost[u]>cost[v]+c[i])
                {
                    cost[u]=cost[v]+c[i];
                    path[u]=v;
                }
            }
        }
    }
}
vector<int> ans;

void dfs(int u)
{
    if(u==s)
    {
        ans.push_back(u);
        for(int i=ans.size()-1;i>=0;i--)
        {
            printf("%d ",ans[i]);
        }
        printf("%d %d",dist[d],cost[d]);
        return;
    }
    ans.push_back(u);
    dfs(path[u]);
}

int main()
{
    scanf("%d%d%d%d",&n,&m,&s,&d);
    memset(h,-1,sizeof h);
    for(int i=0;i<m;i++)
    {
        int a,b,c,d;
        scanf("%d%d%d%d",&a,&b,&c,&d);
        add(a,b,c,d),add(b,a,c,d);
    }
    dijkstra();
    dfs(d);

    return 0;
}

posted @ 2021-03-12 21:14  Daneii  阅读(56)  评论(0编辑  收藏  举报