Warshall算法求傳遞閉包及具體實現

傳遞閉包

在數學中,在集合 X 上的二元關係 R 的傳遞閉包是包含 R 的 X 上的最小的傳遞關係。c++

例如,若是 X 是(生或死)人的集合而 R 是關係「爲父子」,則 R 的傳遞閉包是關係「x 是 y 的祖先」。再好比,若是 X 是空港的集合而關係 xRy 爲「從空港 x 到空港 y 有直航」,則 R 的傳遞閉包是「可能經一次或屢次航行從 x 飛到 y」。

Warshall算法

Warshall在1962年提出了一個求關係的傳遞閉包的有效算法。其具體過程以下,設在n個元素的有限集上關係R的關係矩陣爲M:
(1)置新矩陣A=M;
(2)置k=1;
(3)對全部i若是A[i,k]=1,則對j=1..n執行:
A[i,j]←A[i,j]∨A[k,j];
(4)k增1;
(5)若是k≤n,則轉到步驟(3),不然中止。
所得的矩陣A即爲關係R的傳遞閉包t(R)的關係矩陣。
 
代碼實現:
 1 #include <bits/stdc++.h>
 2 using namespace std;  3 typedef long long ll;  4 typedef unsigned long long ull;  5 #define INF 0x3f3f3f3f
 6 const ll MAXN = 1e3 + 7;  7 const ll MAXM = 1e4 + 7;  8 const ll MOD = 1e9 + 7;  9 const double pi = acos(-1); 10 int Mat[20][20]; // 11 void Print_Mat(int n) 12 { 13     for (int i = 0; i < n; i++) 14  { 15         for (int j = 0; j < n; j++) 16             cout << Mat[i][j] << " "; 17         cout << endl; 18  } 19     return; 20 } 21 void Warshall(int n) 22 { 23     for (int k = 0; k < n; k++) 24         for (int i = 0; i < n; i++) 25             for (int j = 0; j < n; j++) 26                 if (Mat[i][k] && Mat[k][j]) 27                     Mat[i][j] = 1; 28 } 29 int main() 30 { 31     int n; 32     cout << "輸入矩陣階數" << endl; 33     while (cin >> n) 34  { 35         memset(Mat, 0, sizeof(Mat)); 36         cout << "輸入矩陣M:" << endl; 37         for (int i = 0; i < n; i++) 38             for (int j = 0; j < n; j++) 39                 cin >> Mat[i][j]; 40         for (int i = 0; i < n-1; i++) 41  Warshall(n); 42         cout << "矩陣M的傳遞閉包爲:" << endl; 43  Print_Mat(n); 44         cout << "輸入矩陣階數" << endl; 45  } 46     return 0; 47 }

  

相關文章
相關標籤/搜索