day60-graph theory-part10-8.31

tasks for today:

1. bellman_ford 队列优化算法 (SPFA)94.城市间货物运输I

2. bellman_ford 之判断负权回路 95.城市间货物运输II

3. bellman_ford 单源有限最短路 96.城市间货物运输III

----------------------------------------------------------------------------

1. bellman_ford 队列优化算法 (SPFA)94.城市间货物运输I

This is a escalating version of the vanilla bellman_ford algorithm, which mainly concentrates on improving the efficiency through avoiding some repetative relaxation on some uncessary edge. The key idea is to use a que to store the node need to be relax, instead of traversing all the edge as in the vanilla bellman_ford algorithm.

from collections import defaultdict, deque

class Edge:
    def __init__(self, to, value):
        self.to = to
        self.value = value

def main():
    n, m = map(int, input().split())
    
    grid = defaultdict(list)
    
    for _ in range(m):
        s, t, v = map(int, input().split())
        grid[s].append(Edge(t, v))
    
    minDis = [float('inf')] * (n+1)
    
    start = 1
    end = n
    
    minDis[start] = 0
    
    isInQueue = [False] * (n+1)
    
    curQueue = deque()
    curQueue.append(start)
    isInQueue[start] = True
    
    # for _ in range(n-1):
    #     update = False
    #     for edge in grid:
    #         fromNode = edge[0]
    #         toNode = edge[1]
    #         weight = edge[2]
    #         if minDis[fromNode] != float('inf') and minDis[toNode] > minDis[fromNode] + weight:
    #             minDis[toNode] = minDis[fromNode] + weight
    #             update = True
    #     if not update:
    #         break
    
    # print(grid[curQueue.popleft()])

    while curQueue:
        curNode = curQueue.popleft()
        isInQueue[curNode] = False
        edges = grid[curNode]
        for edge in edges:
            fromNode = curNode
            toNode = edge.to
            weight = edge.value
            if minDis[toNode] > minDis[fromNode] + weight:
                minDis[toNode] = minDis[fromNode] + weight
                if not isInQueue[toNode]:
                    curQueue.append(toNode)
                    isInQueue[toNode] = True
    
    if minDis[end] == float('inf'):
        print('unconnected')
    else:
        print(minDis[end])
    
    return


if __name__ == "__main__":
    main()

2. bellman_ford 之判断负权回路 95.城市间货物运输II

In this practice, the setting still allows the negative weights on the edge, which still focus on bellman_ford algorithm, but need some operation on checking if there is circle with negative sum in the graph, which makes the minimum solution does not exist.

For the case where there is no negative circle, after updating n-1 time, the minDis will not be updated anymore, whereas in the case where there is a negative circle, the minDis will keep being updated even after n-1 time. Therefore, as for the vanilla bellman_ford, it is eacy to do the modification to adapt to the case where there might be a negative circle, just do one more update after n-1 times, if the minDis is still changing, then there must be a negative circle in the case.

def main():
    n, m = map(int, input().split())
    
    grid = []
    
    for _ in range(m):
        s, t, v = map(int, input().split())
        grid.append([s, t, v])
    
    minDis = [float('inf')] * (n+1)
    
    start = 1
    end = n
    
    minDis[start] = 0
    
    for i in range(1, n+1):
        update = False
        ifNegCircle = False
        for edge in grid:
            fromNode = edge[0]
            toNode = edge[1]
            weight = edge[2]
            if i < n:
                if minDis[fromNode] != float('inf') and minDis[toNode] > minDis[fromNode] + weight:
                    minDis[toNode] = minDis[fromNode] + weight
                    update = True
            else:
                if minDis[fromNode] != float('inf') and minDis[toNode] > minDis[fromNode] + weight:
                    ifNegCircle = True
        if not update:
            break
                    
    if ifNegCircle:
        print('circle')
    elif minDis[end] == float('inf'):
        print('unconnected')
    else:
        print(minDis[end])
    
    return
 
 
if __name__ == "__main__":
    main()

This practice can also be finished with the bellman_ford SPFA algorithm, the key is to following a rule which says, if one node is added into the curQueue more than n-1 times, that means there should be a negative circle in the graph. Therefore, this necessitates an additional list to monitor the times for each node to be added into the curQueue.

from collections import defaultdict, deque

class Edge:
    def __init__(self, to, value):
        self.to = to
        self.value = value

def main():
    n, m = map(int, input().split())
    
    grid = defaultdict(list)
    
    for _ in range(m):
        s, t, v = map(int, input().split())
        grid[s].append(Edge(t, v))
    
    minDis = [float('inf')] * (n+1)
    
    start = 1
    end = n
    
    minDis[start] = 0
    
    isInQueue = [False] * (n+1)
    
    count = [0] * (n+1)
    
    curQueue = deque()
    curQueue.append(start)
    isInQueue[start] = True
    count[start] += 1
    
    ifNegCircle = False

    while curQueue:
        curNode = curQueue.popleft()
        isInQueue[curNode] = False
        edges = grid[curNode]
        for edge in edges:
            fromNode = curNode
            toNode = edge.to
            weight = edge.value
            if minDis[toNode] > minDis[fromNode] + weight:
                minDis[toNode] = minDis[fromNode] + weight
                if not isInQueue[toNode]:
                    curQueue.append(toNode)
                    isInQueue[toNode] = True
                    count[toNode] += 1
                    if count[toNode] == n:
                        ifNegCircle = True
                        while curQueue: curQueue.popleft()
                        break
    
    if ifNegCircle:
        print('circle')
    elif minDis[end] == float('inf'):
        print('unconnected')
    else:
        print(minDis[end])
    
    return


if __name__ == "__main__":
    main()

3. bellman_ford 单源有限最短路 96.城市间货物运输III

In this practice, you should pay attention to then start and end point, while also the relaxation times for adhering to the requirement of k.

because the maximum points between the start and end is k, there would be maximum k+1 edges between these two points, which allows for k+1 times relaxation.

If we only do above modification on start, end and traverse time, the result would be wrong, becaue there would be negative circle showing up in the graph. This is resolved by add an additional list used to record the minDis in last step.

import copy

def main():
    n, m = map(int, input().split())
    
    grid = []
    
    for _ in range(m):
        s, t, v = map(int, input().split())
        grid.append([s, t, v])
    
    src, dst, k = map(int, input().split())
    
    minDis = [float('inf')] * (n+1)
    
    minDis[src] = 0
    
    for _ in range(k+1):
        minDis_copy = copy.deepcopy(minDis)
        for edge in grid:
            fromNode = edge[0]
            toNode = edge[1]
            weight = edge[2]
            if minDis_copy[fromNode] != float('inf') and minDis[toNode] > minDis_copy[fromNode] + weight:
                minDis[toNode] = minDis_copy[fromNode] + weight

    
    if minDis[dst] == float('inf'):
        print('unreachable')
    else:
        print(minDis[dst])
    
    return
 
 
if __name__ == "__main__":
    main()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值