动态规划在求解传递闭包问题中的应用(JAVA)--Warshell算法
動態規劃在求解傳遞閉包問題中的應用:
傳遞閉包:對于n個頂點有向圖來說,如果第i個頂點到第j個頂點之間存在一條有效的有向路徑(即長度大于0的路徑),那么T(i, j) = 1,否則T(i, j) = 0。例如:
求解傳遞閉包我們可以使用深度優先搜索和廣度優先搜索,我們可以對每個頂點進行DFS/BFS,在對應的矩陣位置上置為1,遍歷之后我們便得到整個圖的傳遞閉包。
但是這種方式并不是高效的算法,而Warshell算法卻能很好的解決問題。
Warshell算法通過一系列n階布爾矩陣來構造傳遞閉包 R(0),...R(k),...,R(n) 。其中的每個布爾矩陣都提供有向圖中有向路徑的特定信息。具體來說,當且僅當從第i個頂點到第j個頂點之間存在一條有向路徑,并且路徑的每一個中間頂點的編號不大于k時,矩陣中第i行第j列的元素值為1。
R(0)中每個點的含義為:當且僅當從第i個頂點到第j個頂點之間存在一條有向路徑,并且路徑不存在中間頂點。即該矩陣為圖的鄰接矩陣。
R(k)中每個點的含義為:當且僅當從第i個頂點到第j個頂點之間存在一條有向路徑,并且路徑的每一個中間頂點的編號不大于k
R(n)中每個點的含義為:當且僅當從第i個頂點到第j個頂點之間存在一條有向路徑,并且路徑的每一個中間頂點的編號不大于n,即圖的傳遞閉包。
思路:任何R(k)可以由R(k-1)計算的到的,那么,從第i個頂點vi到第j個頂點vj的路徑可以表示為:
vi, ]每個頂點編號<=k的一個中間頂點集],vj
這會存在兩種情況,情況一:R(k-1) = 1,中間頂點集中不包含k即可到達vj;
情況二,R(k-1) = 0,中間頂點集必須包含k才能到達vj,那么,只有當矩陣中第i行第k列的元素和第k行第j列的元素都是1,R(k)才能是1。示例如下圖:
下面將以示例的形式具體展示Warshell算法的流程:
Input:
4 4
1 2
2 4
4 1
4 3
Output:
1 1 1 1?
1 1 1 1?
0 0 0 0?
1 1 1 1
完整代碼如下:
import java.util.Scanner;public class Main {static int[][] e = new int[10][10];static int n, m;static Scanner input = new Scanner(System.in);public static void main(String[] args) {n = input.nextInt();m = input.nextInt();for (int i = 1; i <= m; i++) {int a = input.nextInt();int b = input.nextInt();e[a][b] = 1;}floyd();for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {System.out.print(e[i][j] + " ");}System.out.println();}}public static void floyd() {for (int k = 1; k <= n; k++) {for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {if (e[i][j] != 0) {e[i][j] = 1;} else if (e[i][k]!=0 && e[k][j]!=0) {e[i][j] = 1;}}}}} }時間復雜度:O(n^3)
更一般的問題是求解帶權圖中全源最短路徑的長度。
總結
以上是生活随笔為你收集整理的动态规划在求解传递闭包问题中的应用(JAVA)--Warshell算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 吴钩:打开宋代的“隐藏玩法”
- 下一篇: 分享几个病毒分析检测网址