欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

迪杰斯特拉(Dijkstra)算法(Python)

程序员文章站 2022-09-13 23:54:20
#1003 Emergency (25 分)题解(Dijkstra算法)详细注释题目原题传送门三级标题四级标题五级标题六级标题...

程序员入门水平,贴出代码大家一起进步!

原题传送门

题目

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
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
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

思路||总结

  • 主要使用迪杰斯特拉(Dijkstra)算法,但是本题需要记录起始节点到各节点的路径数量和救援队( rescue teams)的数量。
  • 下面的Python代码可以AC,但是其中是有bug的,否则会超时(详见第30行)。

AC代码

import numpy as np


def Input():
    temp = input().strip()
    temp = temp.split(' ')
    n, m, c1, c2 = int(temp[0]), int(temp[1]), int(temp[2]), int(temp[3])
    rescuer = input().strip().split(' ')
    road = np.full((n, n), float('inf'))
    for i in range(n):
        rescuer[i] = int(rescuer[i])
        road[i][i] = 0
    for i in range(m):
        temp = input().strip().split(' ')
        road[int(temp[0])][int(temp[1])] = road[int(temp[1])][int(temp[0])] = int(temp[2])
        # road[int(temp[1])][int(temp[0])] = int(temp[2])
    return n, c1, c2, rescuer, road


def main():
    n, c1, c2, rescuer, road = Input()  # n:节点个数,m:道路数量,c1:起点,c2:重点,rescuer:各个节点团队数量,road:道路距离
    flag = np.zeros(n, bool)  # 设置标志,确认是否已经加入集合S
    num = np.zeros(n, int)  # 起点到每个各个节点的道路的数量
    team = np.zeros(n, int)  # c1到各节点的救援队数量
    dis = np.full(n, float('inf'))  # c1点到各点的距离
    # 数据初始话,节点c1不能初始化到集合S
    num[c1] = 1  # c1到到自身的路径数为1
    team[c1] = rescuer[c1]  # c1自身的救援队数量
    dis[c1] = 0
    for i in range(n-1):  # (外循环)每次向集合S增加一个节点(PS:循环n-1次能通过全部测试且保证不超时,但是这是有bug的,正确的应该是是循环n次,当题目中输入的c2点为4的时候,当循环n次则输出的rescue teams为正确答案9,如果循环n-1次则输出的rescue teams为0)
        # u的值一旦改变则需要更新相关的值
        u = -1
        temp = float('inf')
        for j in range(n):
            if not flag[j] and dis[j] < temp:  # 如果点j不在集合S中且点c1到点j可以联通且是最短的路径
                u = j
                temp = dis[j]
        flag[u] = True  # 将节点u放入集合S
        for v in range(n):
            if not flag[v] and road[u][v] != float('inf'):
                if dis[u] + road[u][v] < dis[v]:  # u为新加入节点,v为当前节点(当通过新加入节点达到当前节点的路径距离小于通过之前的路径距离)
                    num[v] = num[u]
                    dis[v] = dis[u] + road[u][v]
                    team[v] = team[u] + rescuer[v]
                elif dis[u] + road[u][v] == dis[v]:
                    num[v] = num[u] + num[v]
                    team[v] = max(team[v], team[u] + rescuer[v])
    print('flag', flag)
    print('num', num)
    print('dis', dis)
    print('team', team)
    print('{:.0f} {:.0f}'.format(num[c2], team[c2]), end='')


main()

本文地址:https://blog.csdn.net/sinat_41834949/article/details/107167671