生活随笔
收集整理的這篇文章主要介紹了
无向图生成树计数 -- Kirchhoff 矩阵法模板
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Kirchhoff 矩陣法是根據Matrix-Tree定理來的,本人太菜,沒有那個心力去看證明了,知道是用就可以了
作用:
給定一個n個點m條邊的無向圖,求出這個圖的生成樹的總數。
Matrix-Tree定理(Kirchhoff 矩陣-樹定理)
1、G 的度數矩陣 D[G]是?個 n*n 的矩陣,并且滿?:當 i≠j 時,dij=0;當 i=j 時,dij 等于 vi 的度數。
2、G 的鄰接矩陣 A[G]也是?個 n*n 的矩陣, 并且滿?:如果 vi、vj 之間有邊直接相連,則 aij=1,否則為 0。
我們定義 G 的 Kirchhoff 矩陣(也稱為拉普拉斯算?)C[G]為 C[G]=D[G]-A[G],則Matrix-Tree 定理可以描述為:G 的所有不同的?成樹的個數等于其 Kirchhoff 矩陣 C[G]任何?個 n-1 階主?式的?列式的絕對值。所謂 n-1 階主?式,就是對于r(1≤r≤n),將 C[G]的第 r ?、第 r 列同時去掉后得到的新矩陣,? Cr[G]表示。
矩陣樹方法實現:
實現方法很簡單,第一步是構建拉氏矩陣,很簡單。難點在于實現求行列式的值。我這里采用矩陣初等變換將矩陣轉化為上三角矩陣,這樣行列式的值就等于主對角元素乘積。我實現了打印拉氏矩陣C和輸出圖生成樹個數這兩個方法,主體程序如下:
#include<bits/stdc++.h>using namespace std
;class spanningTreeNum {
private:int V
= 0; vector
<vector
<int> > c
;
public:spanningTreeNum(int V
){this->V
= V
;c
= vector
<vector
<int> >(V
, vector
<int>(V
, 0)); }void addEdge(int u
, int v
); int getTreeNum();int det(vector
<vector
<float> > A
); void showC();
};void spanningTreeNum
::addEdge(int u
, int v
) {c
[u
][u
]++; c
[v
][v
]++;c
[u
][v
] = -1; c
[v
][u
] = -1;
}int spanningTreeNum
::det(vector
<vector
<float> > A
) {float res
= 1;int iter
= 0; for (int i
= 0; i
< A
.size(); ++i
) { if(A
[i
][i
]==0) {for (int j
= i
; j
< A
.size(); ++j
) {if(A
[j
][i
]!=0) {swap(A
[i
], A
[j
]);iter
++;}}}for (int j
= i
+1; j
< A
.size(); ++j
) {float temp
= -A
[j
][i
]/A
[i
][i
];for (int k
= 0; k
< A
[j
].size(); ++k
) {A
[j
][k
] = A
[i
][k
]*temp
+A
[j
][k
];}}}for (int i
= 0; i
< A
.size(); ++i
) {res
*= A
[i
][i
];}if(iter
%2==1) res
= -res
;return (int)res
;
}
int spanningTreeNum
::getTreeNum() {vector
<vector
<float > > temp(V
-1, vector
<float >(V
-1, 0));for (int i
= 1; i
< V
; ++i
) {for (int j
= 1; j
< V
; ++j
) {temp
[i
-1][j
-1] = c
[i
][j
];}}return det(temp
);
}void spanningTreeNum
::showC() {for (int i
= 0; i
< c
.size(); ++i
) {for (int j
= 0; j
< c
[i
].size(); ++j
) {printf("%3d ", c
[i
][j
]);}cout
<< endl
;}
}int main()
{spanningTreeNum
G(4);G
.addEdge(0, 1);G
.addEdge(0, 2);G
.addEdge(1, 2);G
.addEdge(2, 3);cout
<< "拉氏矩陣為:" << endl
;G
.showC(); cout
<< "生成樹個數為:" << G
.getTreeNum() << endl
; return 0;
}
運行結果:
總結
以上是生活随笔為你收集整理的无向图生成树计数 -- Kirchhoff 矩阵法模板的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。