zoukankan      html  css  js  c++  java
  • PTA L2-001 紧急救援

    题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805073643683840

    题目大意:就是让你找一个单源最短路,同时还需要能够输出最短路的路径

    输入:

    第一行n,m,s,d,分别是城市数,路径数,起点,终点。

    第二行n个数,是每个城市有的救援队的数目

    接下来m行就是每条道路的两个端点和长度

    输出:

    第一行输出最短路径条数和救援队数量,第二行就是从起点到终点的路径。

    分析:本质上还是用dij做的最短路问题,但需要添加些东西,我们可以用num数组表示从起点到i的最短路径条数,w数组表示救援队数量

    同时最用dij做最短路的时候,把最短路径上每个城市的前驱用pre数组记录下来

    这样,在更新最短路时,如果dis[e.to]>dis[v]+e.cost  就需要将v和e.to连接起来,那么num[e.to]就应该和num[v]保持一致,w[e.to]=w[v]+a[e.to]

    除了大于的情况,对于dis[e.to]==dis[v]+e.cost,我们也需要考虑,因为e.to的最短路径条数除了本身的,还有从v连接过来的,则num[e.to]+=num[v]

    如果w[v]+a[e.to]>w[e.to],那么w[e.to]=w[v]+a[e.to],因为要保证救援队数量最多

    另外每当连路径的时候记得把pre数组录入一下,最后递归输出即可

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 const int inf=1<<30;
     4 typedef long long ll;
     5 typedef pair<int,int> P;
     6 const double pi=acos(-1);
     7 const int mod=1e8+7;
     8 const int maxn=505;
     9 const int maxm=6300;
    10 int dis[maxn];
    11 int a[maxn],num[maxn],w[maxn],pre[maxn];//num数组是出发点到i点时拥有的路径的条数,w数组是救援队的数目 
    12 struct edge{
    13     int to,cost;
    14 };
    15 int x,y,z,n,m,s,d;
    16 vector<edge> g[maxm];
    17 void dij(int s){
    18     priority_queue<P,vector<P>,greater<P> > que;
    19     fill(dis,dis+maxn,inf);
    20     dis[s]=0;
    21     w[s]=a[s],num[s]=1;//初始化,到起始点救援队数量就是起始点本身救援队数量,路径也只有一条 
    22     que.push({0,s});
    23     while(!que.empty()){
    24         P p=que.top();que.pop();
    25         int v=p.second;
    26         if(dis[v]<p.first) continue;
    27         for(int i=0;i<g[v].size();i++){
    28             edge e=g[v][i];
    29             if(dis[e.to]>dis[v]+e.cost){//这种情况肯定要从v到e.to了 
    30                 num[e.to]=num[v];
    31                 w[e.to]=w[v]+a[e.to]; 
    32                 dis[e.to]=dis[v]+e.cost;
    33                 pre[e.to]=v;
    34                 que.push({dis[e.to],e.to});
    35             }
    36             else if(dis[e.to]==dis[v]+e.cost){
    37                 if(w[v]+a[e.to]>w[e.to]){w[e.to]=w[v]+a[e.to];pre[e.to]=v;} 
    38                 num[e.to]+=num[v];    //还要再加上v点的            
    39             }
    40         }
    41     }
    42 }
    43 void print(int c){
    44     if(c==s){
    45         cout<<s;return;
    46     }
    47     print(pre[c]);
    48     cout<<" "<<c;
    49 }
    50 int main(){
    51     scanf("%d%d%d%d",&n,&m,&s,&d);
    52     for(int i=0;i<n;i++) scanf("%d",&a[i]);
    53     for(int i=0;i<m;i++){
    54         scanf("%d%d%d",&x,&y,&z);
    55         g[x].push_back({y,z});
    56         g[y].push_back({x,z});
    57     }
    58     dij(s);
    59     cout<<num[d]<<" "<<w[d]<<endl;
    60     print(d);
    61     cout<<endl;
    62     return 0;
    63 }
  • 相关阅读:
    【剑指offer】面试题16、反转链表
    【剑指offer】面试题15、链表中倒数第 K 个结点
    【剑指offer】面试题14、调整数组顺序使奇数位于偶数前面
    oracle sql与调优
    linux 常用命令记录 持续更新
    函数重载中形参的const
    mem_fun_ref和mem_fun的用法
    c++风格的格式化输出
    count_if函数里面的第三个参数的书写方式<<0926
    操作符重载(++,+,输入输出,强制类型转换)
  • 原文地址:https://www.cnblogs.com/qingjiuling/p/10474820.html
Copyright © 2011-2022 走看看