L2-001. 紧急救援

Posted new-zjw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了L2-001. 紧急救援相关的知识,希望对你有一定的参考价值。

L2-001. 紧急救援

作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。

输入格式:

输入第一行给出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; 
   注意点:
        第一点:当代价相同的时候,到达该点的数目 k[j] = k[j] + k[k1];
        第二点:当你的代价小于它的时候,k[k] = k[i];
*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
using namespace std;

int preoder[505];
int v[505],path[505][505],step[505],k[505],p[505];
int n,m;
int inf = 99999999,ff,si,sj;

void dj()
{
    ///标记确定点的点
    int un[550];
    memset(un,0,sizeof(un));
    ///初始化,开始点为si,到达的数目为1,前驱的能叫到的人员为v[si]
    k[si] = 1;
    step[si] = 0;
    preoder[si] = v[si];
    for(int i=0; i<n; i++)
    {
        ///寻找step[j],最小的点,也就是到那点代价最小的点,开始
        int  k1 =-1,t = inf;
        for(int j=0; j<n; j++)
        {
            if(un[j] == 0 && step[j] < t)
            {
                k1 = j;
                t = step[j];
            }
        }
        ///标记确定的点
        un[k1] = 1;
        for(int j=0; j<n; j++)
        {
            ///表示该点是不是确定的,或者二者之间有没有路径
            if(un[j] == 1 || path[k1][j] == -1)
                continue;
            if(step[j] == step[k1] + path[k1][j])
            {
                k[j] = k[k1] + k[j];
                if(preoder[j] < v[j] + preoder[k1])
                {
                    preoder[j]  = v[j] + preoder[k1];
                    p[j] = k1;
                }
            }
            else if(step[j] > step[k1] + path[k1][j])
            {
                k[j] = k[k1];
                step[j] = step[k1] + path[k1][j];
                preoder[j]  = v[j] + preoder[k1];
                p[j] = k1;
            }
        }
    }

}


void printPath(int v) {
    if(v == si) {
        printf("%d", v);
        return ;
    }
    printPath(p[v]);
    printf(" %d", v);
}

int main()
{
    int si,sj;
    ///表示路径的连通
    memset(path,-1,sizeof(path));
    ///表示前驱
    memset(preoder,0,sizeof(preoder));
    ///表示达到i点的路径数目
    memset(k,0,sizeof(k));
    ///开始模拟
    scanf("%d%d%d%d",&n,&m,&si,&sj);
    ///表示不可达
    for(int i=0; i<n; i++)
        step[i] = inf;
    ///输入给点值
    for(int i=0; i<n; i++)
        scanf("%d",&v[i]);
    int x,y,z;
    for(int i=0; i<m; i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        path[x][y] = z;
        path[y][x] = z;
    }
    dj();
    printf("%d %d\n",k[sj],preoder[sj]);
    printPath(sj);
    printf("\n");
    return 0;
}

以上是关于L2-001. 紧急救援的主要内容,如果未能解决你的问题,请参考以下文章

L2-001. 紧急救援

天梯赛 L2-001 紧急救援

拼题 L2-001 紧急救援 最短路计数+记录路径

L2-001 紧急救援 (dijkstra+dfs回溯路径)

L2-001. 紧急救援

L2-001. 紧急救援