L2-001. 紧急救援

Posted 我只有一件白T恤

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
思路:用深度优先遍历整个图,挨个比较然后保存最短路径,这个运行超时我还能理解,但是就得两分是什么梗?看完答案敲了一遍,就多通过了两个测试点
又是什么梗?第二个测试点有毒!
参考博客:https://blog.csdn.net/strokess/article/details/51339933

有些博客写的不正经,他过了你按照他思路来不一定能过,所有还是要自己掌握好Dijkstra,这个题是个很好的练习。
技术分享图片
#include<iostream>
#include<math.h>
#include<limits.h>
#include<string.h>
using namespace std;
int map[505][505], flag[505], path[505];
int rescue[505];
int n, m, s, d, minlen = INT_MAX, rescuen_last = 0, same = 0;
void dfs(int rescuen, int ss, int load)
{
    if (load>minlen)return;
    if (ss == d){
        if (load < minlen){
            minlen = load;
            same = 1;
            memset(path, 0, sizeof(path));
            rescuen_last = rescuen;
            for (int i = 0; i<n; i++)
                path[i] = flag[i];
            return;
        }
        if (load == minlen)
        {
            same++;
            if (rescuen_last<rescuen){
                memset(path, 0, sizeof(path));
                rescuen_last = rescuen;
                for (int i = 0; i<n; i++)
                    path[i] = flag[i];
            }
            return;
        }
    }
    
    for (int i = 0; i < n; i++)
    {
        if (map[ss][i] != -1 && flag[i] == 0){
            flag[i] = 1;
            dfs(rescuen + rescue[i], i, load + map[ss][i]);
            flag[i] = 0;
        }
            
    }
}
void Print(int ss)
{
    if (ss == d)cout << d << endl;
    else cout << ss << " ";

    for (int i = 0; i < n; i++)
    {
        if (path[i] != 0 && map[ss][i] != -1&&flag[i]==0){
            flag[i] = 1;
            Print(i);
        }
    }
}
int main()
{
    memset(map, -1, sizeof(map));
    memset(rescue, -1, sizeof(rescue));
    memset(flag, 0, sizeof(flag));
    
    cin >> n >> m >> s >> d;
    flag[s] = 1;
    for (int i = 0; i < n; i++)
        cin >> rescue[i];

    for (int i = 0; i < m; i++)
    {
        int ss, dd, len;
        cin >> ss >> dd >> len;
        map[ss][dd] = len;
        map[dd][ss] = len;
    }
    dfs(rescue[s], s, 0);
    if (same == 0){
        cout << "0 0" << endl;
    }
    else{
        cout << same << " " << rescuen_last << endl;
        Print(s);
    }
    
    return 0;
}
暴力未AC代码

 

#include<climits>
#include<cstring>
#include<iostream>
using namespace std;
int map[505][505], flag[505], rescue[505], rescue_n[505];
int path[505], path_n[505], dis[505];
int n, m, s, d;
void Dijstra()
{
    for (int i = 0; i < n; i++){
        dis[i] = INT_MAX;
        flag[i] = 0;
        path_n[i] = 0;
    }
    flag[s] = 1; rescue_n[s] = rescue[s];
    path[s] = s; path_n[s] = 1;
    dis[s] = 0;
    for (int i = 0; i < n; i++)
    {
        if (map[s][i] != -1){
            dis[i] = map[s][i];
            path[i] = s;
            path_n[i] = 1;
            rescue_n[i] = rescue[s] + rescue[i];
        }
    }

    for (int v = 1; v < n; v++)
    {
        int min = INT_MAX, cnt;
        for (int i = 0; i < n; i++)
        if (dis[i] < min&&flag[i] == 0){
            min = dis[i];
            cnt = i;
        }
        flag[cnt] = 1;

        for (int i = 0; i < n; i++)
        {
            if (flag[i] == 1 || map[cnt][i] == -1)continue;
            if (map[cnt][i] + min < dis[i]){
                dis[i] = map[cnt][i] + min;
                rescue_n[i] = rescue_n[cnt] + rescue[i];
                path[i] = cnt;
                path_n[i] = path_n[cnt];
            }
            else if (map[cnt][i] + min == dis[i]){
                path_n[i] += path_n[cnt];

                if (rescue_n[cnt] + rescue[i]>rescue_n[i]){
                    rescue_n[i] = rescue_n[cnt] + rescue[i];
                    path[i] = cnt;
                }
            }
        }
    }


}
void Print(int p)
{
    if (p != s)
        Print(path[p]);
    if (p == d)cout << d << endl;
    else cout << p << " ";
}
int main()
{
    cin >> n >> m >> s >> d;
    for (int i = 0; i < n; i++)
        cin >> rescue[i];
    memset(map, -1, sizeof(map));
    for (int i = 0; i < m; i++)
    {
        int ss, dd, len;
        cin >> ss >> dd >> len;
        map[ss][dd] = len;
        map[dd][ss] = len;
    }

    Dijstra();
    cout << path_n[d] << " " << rescue_n[d] << endl;
    Print(d);
    return 0;
}

 

 

 

 今天不宜代码 

 

 




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

L2-001. 紧急救援

天梯赛 L2-001 紧急救援

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

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

L2-001. 紧急救援

L2-001. 紧急救援