团队天梯赛pta--L2-001 紧急救援 (25分)

题目链接:题目
作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。
输入格式:
输入第一行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0 ~ (N−1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。
第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。
输出格式:
第一行输出最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出结尾不能有多余空格。
输入样例:

4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2

输出:

2 60
0 1 3

思路:
最短路肯定要用dijkstra算法,然后在其中分别加入路径数目、父子节点、救援队数目的记录,具体看代码
代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const int MAX_V=1e5+10;
const int INF=1e8+10; 
typedef pair<int,int> P;
int V,n,m,x,y,a[MAX_V];
vector<P> G[MAX_V];//第一个为长度,第二个为要去的城市 
int d1[MAX_V];
int pre[MAX_V],dp[MAX_V];
ll num[MAX_V];//d1是距离,dp是救援队数目,pre是记录节点,num是路径数目 
bool vis[MAX_V];
void dij(int s,int d[])
{
    priority_queue<P,vector<P>,greater<P> >q;//优先队列,先输出最小值 
    fill(d,d+n+1,INF);
    d[s]=0;
    dp[s]=a[s];
    num[s]=1;
    pre[s]=-1;//初始化 
    q.push({0,s});//加入,第一个是距离,第二个是编号 
    while(!q.empty()){
        P p=q.top();q.pop();//移除
        int u=p.second;
        //cout<<t<<endl;
        if(u==y)return ;//到终点退出 
        if(vis[u])continue;//剪枝
        vis[u]=true;
        for(int i=0;i<G[u].size();i++)
  {
            int v=G[u][i].second,w=G[u][i].first;
            if(d[v]>d[u]+w)
   {
                d[v]=d[u]+w;
                num[v]=num[u];
                pre[v]=u;//更新路径 
                dp[v]=dp[u]+a[v];
                q.push({d[v],v});//加入队列
            }
            else if(d[v]==d[u]+w)//多条最短路 
            {
             num[v]+=num[u];//路径相加 
             if(dp[u]+a[v]>dp[v])
             {
              dp[v]=dp[u]+a[v];
              pre[v]=u;//更新父子节点 
    }
   }
        }
    }
}//求最短路的算法 
int main()
{
 cin>>n>>m>>x>>y;
 for(int i=0;i<n;i++)
 {
  cin>>a[i];
 }
 for(int i=0;i<m;i++)
 {
  int u,v,w;
  cin>>u>>v>>w;
  G[v].push_back({w,u});
  G[u].push_back({w,v});
 }//初始化 
 dij(x,d1);
 vector<int> g;
 for(int i=y;i!=-1;i=pre[i]) 
 {
  g.push_back(i);
 }//逆序 
 reverse(g.begin(),g.end());//翻转 
 cout<<num[y]<<" "<<dp[y]<<endl;
 int sz=g.size();
 for(int i=0;i<sz-1;i++)
 {
  cout<<g[i]<<" "; 
 } 
 cout<<g[sz-1]<<endl;//输出 
 return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

容艾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值