CCF-201609-4-交通規劃
阿新 • • 發佈:2018-12-01
這題照樣套模板,但是有個地方要修改。
題目意思是:求最短路徑的同時還要保證這些路徑的總權值最小
在兩條總權值相等的路徑中,經過結點最多的那個最好。你想想,如果我能從原來已有的結點上再加一條到達目標。是不是好過從上一個結點再拉一條呢。兩條總權值相等,結點數相等的路徑,最後一條邊權值越小的越好。
總的來說,在更新最短路徑的時候,只比對最後一條邊即可(無論結點數誰多誰少,只看最後那條邊就可以),如果最後一條邊比原來的路徑的最後一條邊小,就更新。
程式碼只要在原來的dijkstra演算法上改一下就好了。
直接把“edge[1] + minCost < costs[edge[0]]”的小於號改為小於等於號“edge[1] + minCost <= costs[edge[0]]”。
我這裡新加一個儲存到父結點的邊權值,在每次更新最短路徑的時候,看新的父結點的邊值是否小於以前的,是就更改父結點和父結點邊的權值。修改起來有點麻煩,但是這樣利於後面的算總權值和(總費用)。
這題n最大10000。。。這裡演算法時間複雜度為O(n^2),嗯。。。所以最後只過了80%的用例,80分。後面20%用例執行超時。
python程式碼:
def dij(start, graph): n = len(graph) costs = [99999 for _ in range(n)] parents = [-1 for _ in range(n)] parents_costs = [99999 for _ in range(n)] costs[start] = 0 visited = [False for _ in range(n)] t = [] while len(t) < n: # 每次從costs裡找最短花銷,把最短花銷的結點加進t中 minCost = 99999 minNode = start for i in range(len(costs)): if not visited[i] and costs[i] < minCost: minNode = i minCost = costs[i] t.append(minNode) visited[minNode] = True # 找這點的鄰邊(子結點不在t裡面) # 如果鄰邊的子結點的路徑花銷小於原來的花銷,就更新花銷和父結點 for edge in graph[minNode]: if not visited[edge[0]] and edge[1] + minCost <= costs[edge[0]]: if edge[1] + minCost < costs[edge[0]]: costs[edge[0]] = edge[1] + minCost parents[edge[0]] = minNode parents_costs[edge[0]] = edge[1] elif edge[1] < parents_costs[edge[0]]: parents[edge[0]] = minNode parents_costs[edge[0]] = edge[1] return costs, parents, parents_costs n, m = map(int, input().split()) # 鄰接表 graph = [[] for _ in range(n)] for i in range(m): edge = list(map(int, input().split())) graph[edge[0] - 1].append([edge[1] - 1, edge[2]]) graph[edge[1] - 1].append([edge[0] - 1, edge[2]]) costs, parents, parents_costs = dij(0, graph) # 算總費用 total = 0 for i in range(1, len(parents_costs)): total += parents_costs[i] print(total)