首页 > 编程语言 >1003 Emergency C++

1003 Emergency C++

时间:2023-07-10 22:56:12浏览次数:42  
标签:index dist totalRescue Emergency map ways C++ int 1003

As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.

Input Specification:

Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (≤500) - the number of cities (and the cities are numbered from 0 to N−1), M - the number of roads, C1​ and C2​ - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c1​, c2​ and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C1​ to C2​.

Output Specification:

For each test case, print in one line two numbers: the number of different shortest paths between C1​ and C2​, and the maximum amount of rescue teams you can possibly gather. All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.

Sample Input:

5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1

Sample Output:

2 4

题意:

构造一个无向连通图,求单源最短路径。Dijistra。

分析:

在计算c1到c2的边的权重最小的一条路径的时候,本题还要求找到所有最短的路径,但是不需要记录每条路径,只需要输出个数,用ways数组来记录起点到达终点的最短路径条数(ways数组也包含了起点到达其他顶点的最短路径条数)。另外,这道题还需要记录起点到终点的最大点权和,用totalRescue数组记录起点到达每一个顶点的累积最大点权。Dijistra算法的思路是这样的,用一个顶点集vist来表示已访问的节点,用一个dist数组来记录顶点到达每一个顶点的最短路径值。每次从dist数组里找一个未访问的dist值最小的节点,这个值就是源点到该顶点的最短路径,然后将其标记为已访问,然后需要比较通过新加入的节点到达其他点的路径是否比从源点直接到达更近,如果更近,则更新这些顶点在dist数组里的值。

① 比较 dist[index] + map[index][j] < dist[j],如果满足,则说明通过新加入的节点到达j顶点,比通过原来的路径到达j顶点更短,此时需要更新dist[j],即dist[j] = dist[index] + map[index][j],但此题还需要更新其他的值,因为最短路径变了,到达j点的路径的点权总和也要跟着变,即totalRescue[j] = totalRescue[index] + weight[j],到达j点的最短路径总数也要跟着变,即和新加入的index节点一致, ways[j] = ways[index];

②若dist[index] + map[index][j] == dist[j],说明到达j点的最短路径有多条,即经过新加入的index节点与直接到达j点是一样的。需要更新ways数组,即ways[j] += ways[index],然后更新路径中最大的点权值,判断新加入的路径的点权是否大于原来的,totalRescue[index] + weight[j] > totalRescue[j],如果是,则更新,即totalRescue[j] = totalRescue[index] + weight[j]。

代码:

//
// Created by yaodong on 2023/7/5.
//

#include "iostream"
#include "cstring"

//#define INF 0xfffff
const int INF = 0xffffff;
int main() {
    int n, m, c1, c2;
    std::cin >> n >> m >> c1 >> c2;
    int weight[n];
    for (int i = 0; i < n; ++i) {
        std::cin >> weight[i];
    }
    int begin, end, distance;
    int map[n][n];
    std::fill(map[0], map[0]+n*n, INF);

    for (int i = 0; i < m; ++i) {
        std::cin >> begin >> end >> distance;
        map[begin][end] = distance;
        map[end][begin] = distance;
    }


    int totalRescue[n];     // 记录点的最大权,也就是城市能提供的最大救援队个数
    int visit[n];           // 标记节点是否访问
    int ways[n];            // 记录从起点到每个节点的最短路径条数
    int dist[n];            // 记录从起点到每个节点的最短路径
    memset(visit, 0, sizeof(visit));
    memset(totalRescue, 0, sizeof(totalRescue));
    memset(ways, 0, sizeof(ways));
    std::fill(dist, dist+n, INF);
//    printf("helolo %d\n", dist[1]);

    //Dijistra
    dist[c1] = 0;
    totalRescue[c1] = weight[c1];
    ways[c1] = 1;

    for (int i = 0; i < n; ++i) {
        int index = -1, min = INF;
        // 每次找到距离最短的最小的未访问过的点,最开始是起点c1。
        for (int j = 0; j < n; ++j) {
            if(visit[j] == 0 && dist[j] < min){
                index = j;
                min = dist[j];
            }
        }
        if(index == -1) break;      //如果节点均访问过,则退出
        visit[index] = 1;        //将要访问的节点标记已访问
        
        /* *
         * 算法的思路是这样的,每次从dist数组里找一个最小的,这个值就是源点到该顶点的最短路径
         * 并把该点加入到已访问节点的集合当中,然后需要看新加入的顶点是否可以到达其他顶点,并
         * 比较通过该顶点到达其他点的路径是否比之前的路径直接到达短,如果是,则替换这些顶点在
         * dist数组里的值。
         */
        for (int j = 0; j < n; ++j) {
            if(visit[j] == 0 && map[index][j] != INF){
                if(dist[index] + map[index][j] < dist[j]){
                    dist[j] = dist[index] + map[index][j];
                    totalRescue[j] = totalRescue[index] + weight[j];
                    ways[j] = ways[index];
                }else if(dist[index] + map[index][j] == dist[j]){
                    ways[j] += ways[index];
                    if(totalRescue[index] + weight[j] > totalRescue[j])
                        totalRescue[j] = totalRescue[index] + weight[j];
                }
            }
        }
    }
    printf("%d %d", ways[c2], totalRescue[c2]);
}

 

标签:index,dist,totalRescue,Emergency,map,ways,C++,int,1003
From: https://www.cnblogs.com/langweixianszu/p/17542587.html

相关文章

  • c++_ 贪吃蛇_蛇尾坐标记录问题
    c++_贪吃蛇_蛇尾坐标记录问题思路:利用双指针,把蛇尾的状态数组向后移动1位。intprevX=tailX[0];intprevY=tailY[0];//之前的蛇头坐标给prevX,prevYintprev2X,prev2Y;tailX[0]=x;tailY[0]=y;//更新蛇头坐标for(inti=1;i<nTail;i++)......
  • c++ day 6
    昨天小偷了个懒今天好好搞回来今天还要复习一个概念知识,我这里只是记录我学习过程中的点子。程序性能分析我们先来看一个小故事故事由chatgpt生成 时间复杂度和空间复杂度是分析算法效率和资源消耗的重要指标。让我们逐一了解这两个概念。时间复杂度是衡量算法执行所需......
  • 1002 A+B for Polynomials C++
    Thistime,youaresupposedtofind A+B where A and B aretwopolynomials.InputSpecification:Eachinputfilecontainsonetestcase.Eachcaseoccupies2lines,andeachlinecontainstheinformationofapolynomial:K N1​ aN1​​ N2​ aN2​​ ......
  • 如何使用C++11 STD::THREAD设置堆栈大小?
    本教程将介绍如何使用C++11std::thread设置线程的堆栈大小。C++11std::thread是一种轻量级的多线程实现,它的灵活性使得它成为一个流行的选择。但是,在某些情况下,您可能需要设置线程的堆栈大小来满足您的需求。在开始本教程之前,我们假设您已经熟悉了C++11std::thread的基础知识......
  • 遇到难题了,在线等大佬求解\C++
    intmain(){ characcounts[]={0}; charpassword[]={0}; inti=0; printf("请输入账号:>"); scanf("%s",accounts); (strcmp(accounts,"1234")==0); for(i=1;i<=3;i++) { printf("请输入密码:>"); ......
  • C++程序设计综合实验任选题目[2023-07-10]
    C++程序设计综合实验任选题目[2023-07-10]程序设计综合实验任选题目简单题目题目1模拟ATM机存取款管理系统设计1、问题描述模拟银行的自动取款及使用过程中的界面和用户交互过程。实现查询银行卡余额、取款、修改密码、退出系统等功能。2、功能要求(1)卡号、密码输入最多......
  • python3使用pip安装wordcloud报错error: Microsoft Visual C++ 14.0 or greater is re
    背景:使用的是Anaconda集成环境,python版本是:3.10,安装wordcloud包,使用的命令是:pipinstallwordcloud,出现报错:error:MicrosoftVisualC++14.0orgreaterisrequired.Getitwith"MicrosoftC++BuildTools":https://visualstudio.microsoft.com/visual-cpp-build-tools/......
  • 如何用C++11实现观察者模式
    观察者模式是一种设计模式,定义了对象之间的一对多关系。当一个对象状态发生改变时,它的依赖者都会收到通知并自动更新。在C++11中,可以通过以下方式实现观察者模式:首先,我们需要创建一个观察者接口,其中包含一个更新方法。这个接口可以被多个观察者类实现,从而实现多态。#include<iostr......
  • C++类模板实现工厂模式(优化if else/switch case)
    引自:https://blog.csdn.net/weixin_43795921/article/details/127224633template<typenameIdentifierType,classAbstractProduct,classProductCreator=AbstractProduct*(*)(),classMapContainer=std::map<IdentifierType,ProductCreato......
  • C++ 数据抽象
     数据抽象是指,只向外界提供关键信息,并隐藏其后台的实现细节,即只表现必要的信息而不呈现细节。数据抽象是一种依赖于接口和实现分离的编程(设计)技术。让我们举一个现实生活中的真实例子,比如一台电视机,您可以打开和关闭、切换频道、调整音量、添加外部组件(如喇叭、录像机、DVD播......