程式碼隨想錄演算法訓練營day58| 117.軟體構建 47.參加科學大會

Tristan241001發表於2024-11-26

學習資料:https://www.programmercarl.com/kamacoder/0117.軟體構建.html#拓撲排序的背景

圖論
拓撲排序:收集入度為0的節點,刪掉該節點後其他節點的入度可能變化,記得更新,然後繼續刪除入度為0的點,直到沒有。整個過程的順序就對應了有向圖
dijkstra演算法:類似prim,也是貪心,找距離源點最近的節點,設定該節點為以訪問,更新其他未訪問節點到源點的最短距離

學習記錄:
117.軟體構建

點選檢視程式碼
# 拓撲排序:將關係轉換為有向圖,線性排序(如果有環,迴圈依賴則不行)
# 具體思路:統計每個節點的入度和出度;如果入度為0而有入度則為根;
# 依次刪除入度為0的點,記住要更新剩下節點的入度,都會-1

from collections import deque, defaultdict

def topological_sort(n, edges):
    # 構造一個記錄節點入度的列表,初始設定為0
    inDegree = [0]*n
    # 記錄節點間的依賴關係
    umap = defaultdict(list)  # 每個鍵的預設值都是空列表[]
    
    # 構建圖和入度表(s有多少個下一級),s->t,則t的入度+1
    for s, t in edges:
        inDegree[t] += 1
        umap[s].append(t)
    
    # 初始化佇列,加入所有入度為0的節點,再一個一個處理
    queue = deque([i for i in range(n) if inDegree[i]==0])
    result = []
    
    while queue:
        cur = queue.popleft()
        result.append(cur)   # 把第一個根加入結果中,並討論刪除這個節點後其他節點的入度變化情況
        for file in umap[cur]:
            inDegree[file] -= 1
            if inDegree[file] == 0:   # 當出現新的根,及時加入佇列中
                queue.append(file)
    
    if len(result)==n:
        print(" ".join(map(str, result)))
    else:
        print(-1)


# 輸入值
n, m = map(int, input().split())
edges = []
for _ in range(m):
    edges.append(list(map(int, input().split())))
topological_sort(n, edges)


47.參加科學大會(沒看懂!!)

點選檢視程式碼
# dijkstra演算法,類似於prim
# 統計每個節點到源點的最小距離(minDist),和是否被訪問過(visited)
# 找到距離源點最近的未訪問過的節點,選中它;將它標記為訪問過;更新minDist

def dijkstra(n, m, start, end):
    # 初始化鄰接矩陣,每個節點到源點的距離都設定為無窮大,因為後面要儲存最短距離
    grid = [[float('inf')]*(n+1) for _ in range(n+1)]
    for p1, p2, val in edges:
        grid[p1][p2] = val
    
    # 初始化距離陣列,都為無窮大
    minDist = [float('inf')]*(n+1)
    minDist[start]=0  # 自己到自己的距離為0
    # 訪問陣列,初始為未訪問
    visited = [False]*(n+1)
    
    # 遍歷所有節點
    for _ in range(1, n+1):
        minVal = float('inf')
        cur = -1
        
        # 選擇距離源點最近且未訪問過的節點
        for v in range(1, n+1):
            if not visited[v] and minDist[v]<minVal:
                minVal = minDist[v]
                cur = v
        # 若節點都訪問過,則提前結束
        if cur == -1:
            break
        # 標記該節點為被訪問
        visited[cur] = True
        
        # 更新剩餘未訪問節點到源點的距離 ????? 真沒看懂啊!!!!!
        for v in range(1, n+1):
            if not visited[v] and grid[cur][v] != float('inf') and minDist[cur]+grid[cur][v]<minDist[v]:
                minDist[v] = minDist[cur]+grid[cur][v]
    return -1 if minDist[end]==float('inf') else minDist[end]
    
# 輸入值
n, m = map(int, input().split())
edges = []
for _ in range(m):
    edges.append(list(map(int, input().split())))
start = 1
end = n
result = dijkstra(n, m, start, end)
print(result)


PS:今天更冷了,多雲
題看懂了一道,圖論多回顧學習
今天吃了食堂的手工扯麵,快半年沒吃過了,好吃的!吃了雞公煲,一如既往的好吃。
今天好睏,論文接近尾聲了,加油
找工作啥時候是個頭啊,我只是一個愛生活的小菜鳥

相關文章