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

python使用 Dijkstra算法解决--温差最小路径问题

程序员文章站 2022-03-14 21:21:58
问题描述一些村庄由许多条小路连接,由于每条小路处于不同的地理位置,因此每条小路上的温度是不一样的。村民们要前往另一村庄时,对这条路径的绝对温度没有要求,但若一条路径的最大温度与最低温度之间的温差过大,会导致感冒。请你找出两个村庄间的温差最小的路径。输入第一行是一个正整数q,表示测试例数量。对每个测试例第一行有2个整数n(1

问题描述

一些村庄由许多条小路连接,由于每条小路处于不同的地理位置,因此每条小路上的温度是不一样的。村民们要前往另一村庄时,对这条路径的绝对温度没有要求,但若一条路径的最大温度与最低温度之间的温差过大,会导致感冒。
请你找出两个村庄间的温差最小的路径。

输入

  • 第一行是一个正整数q,表示测试例数量。
  • 对每个测试例
    第一行有2个整数n(1<n≤400)和m(m≤2000),表示有n个村庄和m条小路。
    接下来m行都是3个正整数,分别是小路起始村庄号,小路终止村庄号,小路上的温度T(T≤2000000)。
    然后有一个正整数P(P≤10),表示寻路次数。
    接下来P行,每行有2个正整数,分别表示村民的起始村庄号,村民的目的村庄号。

输出

每个寻路打印一行,表示温差最小的温差,若不能到达,输出-1.

输入样例

1
5 5
1 2	2
1 5	6
2 5	7
3 4	4
3 5	8
2
1 3
1 2

python使用 Dijkstra算法解决--温差最小路径问题

输出结果

2
0

解题思路

python使用 Dijkstra算法解决--温差最小路径问题

代码实现

#!/usr/bin/env python3
#temperature.py
#fumiama 20201120

from heapq import heappop, heappush, heapify

class UnionFindSet(object):
    def __init__(self, nodes):
        self.fatherMap = {}
        self.setNumMap = {}
        for node in nodes:
            self.fatherMap[node] = node
            self.setNumMap[node] = 1
    def findFather(self, node):
        father = self.fatherMap[node]
        if (node != father):
            father = self.findFather(father)
        self.fatherMap[node] = father
        return father
    def isSameSet(self, a, b):
        return self.findFather(a) == self.findFather(b)
    def union(self, a, b):
        if a is None or b is None: return
        aFather = self.findFather(a)
        bFather = self.findFather(b)
        if (aFather != bFather):
            aNum = self.setNumMap[aFather]
            bNum = self.setNumMap[bFather]
            if (aNum <= bNum):
                self.fatherMap[aFather] = bFather
                self.setNumMap[bFather] = aNum + bNum
                self.setNumMap.pop(aFather)
            else:
                self.fatherMap[bFather] = aFather
                self.setNumMap[aFather] = aNum + bNum
                self.setNumMap.pop(bFather)

class Node(object):
    def __init__(self, name):
        self.name = name
        self.distance = 0
        self.path = [name]
        self.maxT = -1
        self.minT = 2000001
    def __repr__(self):
        return "号节点" + ", 最短路径花费"+ str(self.distance)+ ": " + str(self.path) + '\n'
    def setNode(self, preNode, tempDiff):
        self.distance = tempDiff
        self.path = preNode.path[:]
        self.path.append(self.name)
    def getNewTempDiff(self, temp):
        minT = self.minT
        maxT = self.maxT
        return (temp if temp > maxT else maxT) - (temp if temp < minT else minT)
    def setStartTemp(self, temp): self.maxT = self.minT = temp

class Graph(object):
    def __init__(self, nodeCnt):
        self.nodes = dict()
        self.node2edge = dict()
        self._node2edge = dict()
        self.nodeNames = set()
        self.nodeCnt = nodeCnt
    def __repr__(self):
        return "图共有" + str(self.nodeCnt) + "个节点如下:\n " + str(self.nodes)
    def addEdge(self, start, end, weight):      #无向图
        self._addEdge(start, end, weight)
        self._addEdge(end, start, weight)
    def _addEdge(self, start, end, weight):     #有向图
        if start not in self.nodes.keys(): self.nodes[start] = Node(start)
        newEdge = (weight, end)
        if start not in self.node2edge.keys():
            self.node2edge[start] = {newEdge}
            self._node2edge[start] = {newEdge}
        else:
            self.node2edge[start].add(newEdge)
            self._node2edge[start].add(newEdge)
        if start not in self.nodeNames: self.nodeNames.add(start)
        if end not in self.nodeNames: self.nodeNames.add(end)
    def resetNode2Edge(self): self.node2edge = self._node2edge.copy()
    def getMinTempDiff(self, start, end):
        wedge = []
        for e in self.node2edge[start]:
            wedge.append((0, start, e[1]))
            self.nodes[e[1]].setStartTemp(e[0])
            self.node2edge[e[1]].remove((e[0], start))
        self.node2edge[start] = set()
        forest = UnionFindSet(self.nodeNames)
        result = -1
        while wedge:
            #print("带权边界边:", wedge)
            minEdge = heappop(wedge)
            thisNode = self.nodes[minEdge[1]]
            nextNode = self.nodes[minEdge[2]]
            if not forest.isSameSet(thisNode.name, nextNode.name):
                nextNode.setNode(thisNode, minEdge[0])
                if nextNode.name == end:
                    result = nextNode.distance
                    break
                edgesOfNextNode = self.node2edge[nextNode.name]
                while edgesOfNextNode:
                    edge = edgesOfNextNode.pop()
                    self.node2edge[edge[1]].remove((edge[0], nextNode.name))
                    heappush(wedge, (nextNode.getNewTempDiff(edge[0]), nextNode.name, edge[1]))
                forest.union(thisNode.name, nextNode.name)
        return result

if __name__ == '__main__':
    q = int(input())
    while q:
        n, m = map(int, input().split())
        g = Graph(n)
        while m:
            a, b, t = map(int, input().split())
            g.addEdge(a, b, t)
            m -= 1
        p = int(input())
        while p:
            a, b = map(int, input().split())
            print(g.getMinTempDiff(a, b))
            g.resetNode2Edge()
            p -= 1
        q -= 1

本文地址:https://blog.csdn.net/u011570312/article/details/110289786