PAT A1030 Travel Plan【SPFA+输出路径】

本题是一道最短路径水题,和普通最短路径不一样的是,本题不仅要考虑路径长度,还要考虑路径上的花费。除此之外,还要输出路径。考虑路径上的花费比较简单,直接在SPFA的时候添加判断即可,输出路径则在存边的时候开两个数组,一个专门存前驱,一个专门存后继。在最后,倒序遍历,就可以找到唯一的一条最短路径。

#include <iostream>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<map>
#include<cstdlib>
#include<queue>
#include<cstring>
#include<set>
using namespace  std;
int n,m,s,t;
int c[520];
int in[520]={0};//节点是否在队列中
int dis[520];
int cost[520];
queue<int>q;
set<int>pre[520];//每个节点的前驱节点
struct Node
{
    int v;
    int w;
    int u;
    int cost;
    Node(int _u,int _v,int _w,int _cost):u(_u),v(_v),w(_w),cost(_cost){

    }
};
vector<Node>a[520];
vector<Node>b[520];
int main()
{

    scanf("%d%d%d%d",&n,&m,&s,&t);
    fill(dis+0,dis+n+10,0x3f3f3f3f);
    fill(cost,cost+n+10,0x3f3f3f3f);

    for(int i=1;i<=m;i++)
    {

        int x,y,z,zz;
        scanf("%d%d%d%d",&x,&y,&z,&zz);

        a[x].push_back(Node(x,y,z,zz));
        a[y].push_back(Node(y,x,z,zz));
        b[x].push_back(Node(y,x,z,zz));
        b[y].push_back(Node(x,y,z,zz));

    }

    in[s]=1;
    dis[s]=0;
    cost[s]=0;
    q.push(s);
    while(!q.empty())
    {
        int head=q.front();
        q.pop();
        in[head]=0;
        for(int i=0;i<a[head].size();i++)
        {
            int dis1=a[head][i].w;
            int cost1=a[head][i].cost;
            int v=a[head][i].v;
            if(dis[v]>dis[head]+dis1)
            {
                dis[v]=dis[head]+dis1;
                cost[v]=cost[head]+cost1;

                if(!in[v])
                {
                    in[v]=1;
                    q.push(v);
                }

            }
            else if(dis[v]==dis[head]+dis1)
            {
                if(cost[v]>cost[head]+cost1)
                {
                    cost[v]=cost[head]+cost1;

                    if(!in[v])
                    {
                        in[v]=1;
                        q.push(v);
                    }

                }
            }
        }
    }


    vector<int>ans;

    int cur=t;
    while(true)
    {
        ans.push_back(cur);
        if(cur==s)
            break;
        for(int i=0;i<b[cur].size();i++)
        {
            int u=b[cur][i].u;
            int w=b[cur][i].w;
            int ww=b[cur][i].cost;
            if(dis[cur]==dis[u]+w&&cost[cur]==cost[u]+ww)
            {
                cur=u;
                break;
            }
        }
    }

    for(int i=ans.size()-1;i>=0;i--)
    cout<<ans[i]<<" ";
    cout<<dis[t]<<" "<<cost[t];

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值