首页 > 其他分享 >团体天梯练习 L2-001 紧急救援

团体天梯练习 L2-001 紧急救援

时间:2023-04-16 23:13:11浏览次数:35  
标签:int 救援队 短路 个数 001 L2 天梯 team include

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算法的基础上增加一个最短路计数和救援队个数记录即可。

最短路计数

最短路计数用到的其实是一种动态规划的思想,初始情况下,到达源点最短路径个数记为1。当到达点v最短路可以由点u更新得更小时,到达点u最短路个数需要继承给到达v的最短路个数;如果到达点v的最短路距离和当前由u到达v的距离一样,此时说明有另一条同样长度的最短路,所以到达点v最短路个数需要加上到达点u的最短路个数。

救援队个数

而初始情况下的救援队个数,其实就是每个点的点权。也是一种动态规划的思想,初始情况下,到达源点的最多救援队个数记为源点处的救援队个数team[src]。当到达点v最短路可以由u更新得更小时,很明显,由于题中要求最短的前提下最多救援队个数,所以此时一定要更新到达v的最多救援队个数;当到达v的最短路距离此时和由u更新得到的最短路距离相等,此时就需要判断一下到达救援队个数是否可以更新得更大了,如果能更新得更大,记得别忘了更新v前驱为u。

输出答案

由于dijkstra记录的是最优路径上每个点的前驱,为了正序输出路径,可以先将所有点放入栈中,然后再依次去出,这样就正好是正序的路径了。

关于代码

我用的是堆优化版的dijkstra,用链式前向星存图,自己写这个比较顺手而已。(也可以用vector邻接表存图,用朴素dijkstra)

/*   一切都是命运石之门的选择  El Psy Kongroo  */
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<deque>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<cmath>
#include<functional>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<int, pii> piii;
typedef pair<double, double> pdd;
typedef pair<string, pii> psi;
typedef __int128 int128;
#define PI acos(-1.0)
#define x first
#define y second
//int dx[4] = {1, -1, 0, 0};
//int dy[4] = {0, 0, 1, -1};
const int inf = 0x3f3f3f3f, mod = 1e9 + 7;

const int N = 510, M = N * N;
int h[N], e[M], ne[M], w[M], idx;
int n, m, src, des;
int team[N], team_to[N];   //team[i]表示点i上的队伍个数 team_to[i]表示到达点i的队伍总数
int num[N];   //num[i]表示到达点i的路径总数
int dist[N];  //最短路
int pre[N];   //pre[i]记录前驱
bool st[N];   

void add(int a, int b, int c){
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
}

void dijkstra(){
    memset(pre, -1, sizeof(pre));
    memset(dist, 0x3f, sizeof(dist));
    dist[src] = 0, team_to[src] = team[src], num[src] = 1;  //初始情况
    priority_queue<pii, vector<pii>, greater<pii> > q;
    q.push({0, src});

    while(!q.empty()){
        auto [d, u] = q.top();
        q.pop();

        if(st[u]) continue;
        st[u] = true;

        for(int i = h[u]; ~i; i = ne[i]){
            int v = e[i], c = w[i];
            if(dist[v] > d + c){
                //距离更短 最短路个数要继承,同时更新队伍个数
                dist[v] = d + c;
                team_to[v] = team_to[u] + team[v], num[v] = num[u];
                q.push({dist[v], v});
                pre[v] = u;   //记录前驱
            }else if(dist[v] == d + c){
                //距离相等 最短路个数要累加
                num[v] += num[u];
                if(team_to[v] < team_to[u] + team[v]){
                    //如果当前队伍数小于可以更新的队伍数 则更新
                    team_to[v] = team_to[u] + team[v];
                    pre[v] = u;   //同时更新前驱
                }
            }
        }
    } 
}

void show(){
    int res[N], top = -1;
    int t = des;
    while(t != -1) res[ ++ top] = t, t = pre[t];   //具体路径放入栈中

    cout << num[des] << ' ' << team_to[des] << endl;  //输出路径总数 和 到达队伍总数
    while(top > 0) cout << res[top -- ] << ' ';  //输出具体路径
    cout << res[top];
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    memset(h, -1, sizeof(h));
    cin >> n >> m >> src >> des;
    for(int i = 0; i < n; i ++ ) cin >> team[i];
    while(m -- ){
        int u, v, c; cin >> u >> v >> c;
        add(u, v, c), add(v, u, c);
    }

    dijkstra();

    show();

    return 0;
}

标签:int,救援队,短路,个数,001,L2,天梯,team,include
From: https://www.cnblogs.com/MAKISE004/p/17324256.html

相关文章

  • APP爬虫初阶之Pixel2刷机root
    pixel2刷机刷机准备lineageziptwrpimgmagiskzip(github上下的是APK,需要把后缀改为zip)刷机步骤首先需要一个底包,这里我用的出厂自带的google官方系统,没有重新刷入手机上打开usb调试,关闭屏幕超时锁屏,打开OEM锁手机完全关机,按住向下键重启(或者通过adbrebootbootl......
  • 最后一周天梯赛
    感觉很难害题目有一长度为N(1<=N<=10)的地板,给定两种不同瓷砖:一种长度为1,另一种长度为2,数目不限。要将这个长度为N的地板铺满,一共有多少种不同的铺法?输入格式输入有多组,每组只有一个数N,代表地板的长度输出格式对于每组数据,输出一个数,占一行,代表所有不同的瓷砖铺放方法......
  • 扎实打牢数据结构算法根基,从此不怕算法面试系列之001 week01 02-01 什么是算法?
    1、什么是算法?为了明确什么是算法,我们会从简单的查找功能开始讲起。查找其实一个一个非常简单的算法,但我们会为这个查找功能的算法做如下工作:让查找的功能适应更多的数据类型通过查找的例子讲解如何编写正确的程序?为查找算法性能测试对一些常见算法做复杂度分析2、定义......
  • ESP3D ESP32-C3 bulid时报错 'Serial2' was not declared in this scope
    ESP3D版本: 3.0.0-alpha3 错误原因: ESP32-C3只有两个port 解决方法一: github上最新的git已经解决了该问题,使用git获取最新版,不要下载Release的 解决方法二: 去掉Serial2serial_sevice.cpp中,  第40,41行将MAX_SERIAL的值......
  • [oeasy]python00134_[趣味拓展]python起源_历史_Guido人生_ABC编程语言_Tanenbaum
    python历史回忆上次内容颜文字是kaomoji把字符变成一种图画的方法一层叠一层很多好玩儿的kaomoji是一层层堆叠起来的meme虚拟的表情也在真实世界有巨大影响一步步地影响字符编码就是这样一步步发展过来的python也是一步步发展到今天的python究竟是怎么发展的呢?......
  • windows10 安裝wsl2
    1下载wslwsl--install2下好后重启电脑,我的重启后就自动帮我下了如果没有自动下载wsl--install-dubuntu设置用户名密码4更新sudoaptupdatesudoaptupgrade按Y确认5安装WindowsTerminalPreviewWindowsTerminalPreviewsudoaptinstallwslussl......
  • [oeasy]python00134_[趣味拓展]python起源_历史_Guido人生_ABC编程语言_Tanenbaum
    python历史回忆上次内容颜文字是kaomoji把字符变成一种图画的方法一层叠一层很多好玩儿的kaomoji是一层层堆叠起来的meme ​ 添加图片注释,不超过140字(可选) 虚拟的表情也在真实世界有巨大影响一步步地影响 ​......
  • 「解题报告」AGC001F Wide Swap
    首先题目给的限制条件很奇怪,下标差\(K\)而值域差\(1\)。我们变成逆排列,然后就转换成了下标差\(1\),值域差\(K\)了,每次操作就相当于交换相邻的两个差\(\geK\)的数。假设新的逆排列为\(Q_i\)。我们发现,假如存在两个数差\(<K\),那么它们的相对位置关系一定不变。那么我们现......
  • 基于L2-RLS算法的目标跟踪算法matlab仿真,可处理小范围遮挡问题
    1.算法仿真效果matlab2022a仿真结果如下:2.算法涉及理论知识概要目标表观模型是跟踪器的重要组成部分,用来描述目标表观的特征.基于判别式模型的表观模型用来区分目标和背景;基于生成式模型的表观模型用来描述目标本身,提取出目标的特征.本文合理地融合了判别式模型和生成式模型......
  • 基于L2-RLS算法的目标跟踪算法matlab仿真,可处理小范围遮挡问题
    1.算法仿真效果matlab2022a仿真结果如下:            2.算法涉及理论知识概要       目标表观模型是跟踪器的重要组成部分,用来描述目标表观的特征.基于判别式模型的表观模型用来区分目标和背景;基于生成式模型的表观模型用来描述目标本身,提取......