PTA L2 001 紧急救援总结(Dijkstra用STL优先队列+邻接表求最短路径数量)

题目链接

题目大意
在一张无向网中,每个结点都有自己的权值,每条路径也有对应的权值,求源点s到终点d的最短路径,在保证最短路径的情况下求出经过结点权值的最大值,并输出最短路径经过的结点编号。

解题思路
这是一道很明显的最短路径的模板题。但要注意题目要求计算出最短路径的数量和经过的路径。

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f3f3f3f
#define Max_N 500+5
#define mod 10000019
using namespace std;
typedef pair<int,int>P;//first是最短距离,second是顶点编号
typedef long long ll;
typedef unsigned long long ull;
struct endg
{
    int to;
    int cost;
};//邻接表存图
int pre[Max_N];//用来保存每个结点的前驱
vector<endg>G[Max_N];//无向图
int d[Max_N], maxval[Max_N],pathcount[Max_N];//最短距离,最大权值和,路径数量
int number[Max_N];//每个结点的权值
void dijk(int s,int n)
{
    priority_queue<P,vector<P>,greater<P> >que;//自定义优先队列
    fill(d,d+n+1,INF);//初始化所有结点的最短距离为无穷大
    d[s]=0;//到源点的距离为0
    pathcount[s]=1;//到源点的路径数量为1
    maxval[s]=number[s];
    que.push(P(0,s));
    while(!que.empty())
    {
        P p=que.top();
        que.pop();
        int v=p.second;
        if(d[v]<p.first)
            continue;//当取出来的距离不是最短距离就丢弃
        for(int i=0;i<G[v].size();i++)//遍历顶点v连接的所有结点
        {
            endg e=G[v][i];
            if(d[e.to]>d[v]+e.cost)//如果最短距离可以更小则更新
            {                      
                d[e.to]=d[v]+e.cost;
                pre[e.to]=v;
                maxval[e.to]=maxval[v]+number[e.to];
                pathcount[e.to]=pathcount[v];
                que.push(P(d[e.to],e.to));
            }
            else if(d[e.to]==(d[v]+e.cost))//如果相等,在更新路径数量
            {
                pathcount[e.to]+=pathcount[v];
                if(maxval[e.to]<maxval[v]+number[e.to])
                //在两条路径中选择最大权值和的那条
                {
                    maxval[e.to]=maxval[v]+number[e.to];
                    pre[e.to]=v;
                }
            }
        }
    }

}
int main(int argc, char const *argv[])
{
    int n,m,s,d;
    //freopen("data.txt","r",stdin);
    cin>>n>>m>>s>>d;
    memset(pre,-1,sizeof(pre));
    for(int i=0;i<n;i++)
    {
        cin>>number[i];
    }
    for(int i=0;i<m;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        endg mid1={b,c};
        endg mid2={a,c};
        G[a].push_back(mid1);//无向图
        G[b].push_back(mid2);//无向图
    }
    dijk(s,n);
    cout<<pathcount[d]<<" "<<maxval[d]<<endl;
    vector<int>path;
    for(;d!=-1;d=pre[d])
    {
        path.push_back(d);
    }
    reverse(path.begin(),path.end());
    for(int i=0;i<path.size();i++)
    {
        if(i)
            cout<<" ";
        cout<<path[i];
    }
	cout<<endl;
    return 0;
}

总结
自我感觉这道题有点dp的味道,用数组去存每个结点的信息,在求最短路径的过程中不断去更新。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值