程式碼隨想錄演算法訓練營第52天 | 圖論基礎1

哆啦**發表於2024-07-30

圖論理論基礎
https://www.programmercarl.com/kamacoder/圖論理論基礎.html#圖的基本概念
深度優先搜尋理論基礎
https://www.programmercarl.com/kamacoder/圖論深搜理論基礎.html#深搜三部曲
98.所有可達路徑
https://kamacoder.com/problempage.php?pid=1170
程式碼隨想錄
https://www.programmercarl.com/kamacoder/0098.所有可達路徑.html
廣度優先搜尋理論基礎
https://www.programmercarl.com/kamacoder/圖論廣搜理論基礎.html

圖論基礎

  • 圖種類

    • 有向圖和無向圖;
    • 加權無向圖和加權有向圖;
    • 無向圖:邊的個數
    • 有向圖:入度(指向該節點的個數) 和 出入 (從該節點出發的個數)
  • 連通性

    • 無向圖-連通圖:任何節點都可以達到;
    • 有向圖- 強連通圖:任何兩個節點可以互相達到;
  • 連通分量

    • 在無向圖中:極大連通子圖就是該圖的連通分量;如下圖的(1,2,5)節點和(3,4,6)節點;
      image
    • 強連通分量:有向圖中,極大強連通子圖稱之為該圖的強連通分量;如下圖(6,7,8)和(1,2,3,4,5)的圖;
      image
  • 圖的構造

    • 鄰接表;鄰接矩陣;類;
    • 樸素儲存;鄰接表;鄰居矩陣;
  • 鄰接矩陣

    • 二維陣列表示圖結構;
    • 節點表示圖
    • grid[2][5]=6 grid[5][2]=6 說明grid中2和5節點中有一邊;
  • 鄰接表

    • 陣列+連結串列;
    • 從邊的角度儲存圖
      image

圖的遍歷方式

  • 深度優先搜尋(dfs)
  • 廣度優先搜尋(bfs)

深度優先搜尋理論基礎

概念

  • 向一個方向搜尋,遇到絕境就回溯,繼續;

程式碼框架

  • 因為有路徑回溯和路徑選擇;
  • 所以是遞迴+回溯的過程;
void dfs(引數) {
    if (終止條件) {
        存放結果;
        return;
    }

    for (選擇:本節點所連線的其他節點) {
        處理節點;
        dfs(圖,選擇的節點); // 遞迴
        回溯,撤銷處理結果
    }
}

深搜三部曲

  1. 確認遞迴函式、引數;
void dfs(引數)
  • 二維陣列儲存所有路徑;路徑以一維陣列保持;
  • 全域性變數儲存
  1. 確認終止條件;
if (終止條件) {
    存放結果;
    return;
}
  1. 處理目前搜尋節點出發的路徑;
for (選擇:本節點所連線的其他節點) {
    處理節點;
    dfs(圖,選擇的節點); // 遞迴
    回溯,撤銷處理結果
}

98. 所有可達路徑

題解

採用鄰接矩陣方式

  • 該方式採用鄰接矩陣方式儲存資料
  • 嚴格按照模版進行遍歷
點選檢視程式碼
```python
def dfs(graph,x,n,res,path):
	if x==n:
		res.append(path.copy())
		return
	for i in range(1,n+1):
		if graph[x][i]==1:
			path.append(i)
			dfs(graph,i,n,res,path)
			path.pop()

def main():
	n,m = map(int,input().split())
	graph =[[0]*(n+1) for _ in range(n+1)]
	for i in range(m):
		s,t = map(int,input().split())
		graph[s][t] = 1
	path = [1]
	res = []
	dfs(graph,1,n,res,path)
	if not res:
		print(-1)
		return
	for path in res:
		print(" ".join(map(str,path)))
if __name__ == '__main__':
	main()
```
</details>

採用鄰接列表方式

  • 採用 from collections import defaultdict方式

    點選檢視程式碼
    from collections import defaultdict
    def dfs(graph,x,n,path,res):
    	if x==n:
    		res.append(path.copy())
    		return
    	for i in graph[x]:
    		path.append(i)
    		dfs(graph,i,n,path,res)
    		path.pop()
    def main():
    	n,m = map(int,input().split())
    	graph = defaultdict(list)
    	for i in range(m):
    		s,t = map(int,input().split())
    		graph[s].append(t)
    	# print(graph)
    	res = []
    	path = [1]
    	dfs(graph,1,n,[1],res)
    	if not res:
    		print(-1)
    	else:
    		for path in res:
    			print(" ".join(map(str,path)))
    
    if __name__ == '__main__':
    	main()
    

廣度優先搜尋理論基礎

使用場景

  • 解決兩點之間的最短路徑問題
  • 不涉及具體遍歷方式,只要把相鄰和相同屬性的節點標記上即可;

廣搜過程

  • 一圈一圈搜尋
    image

相關文章