生活随笔
收集整理的這篇文章主要介紹了
无向图生成树计数 -- Kirchhoff 矩阵法模板
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Kirchhoff 矩陣法是根據(jù)Matrix-Tree定理來的,本人太菜,沒有那個(gè)心力去看證明了,知道是用就可以了
作用:
給定一個(gè)n個(gè)點(diǎn)m條邊的無向圖,求出這個(gè)圖的生成樹的總數(shù)。
Matrix-Tree定理(Kirchhoff 矩陣-樹定理)
1、G 的度數(shù)矩陣 D[G]是?個(gè) n*n 的矩陣,并且滿?:當(dāng) i≠j 時(shí),dij=0;當(dāng) i=j 時(shí),dij 等于 vi 的度數(shù)。
2、G 的鄰接矩陣 A[G]也是?個(gè) n*n 的矩陣, 并且滿?:如果 vi、vj 之間有邊直接相連,則 aij=1,否則為 0。
我們定義 G 的 Kirchhoff 矩陣(也稱為拉普拉斯算?)C[G]為 C[G]=D[G]-A[G],則Matrix-Tree 定理可以描述為:G 的所有不同的?成樹的個(gè)數(shù)等于其 Kirchhoff 矩陣 C[G]任何?個(gè) n-1 階主?式的?列式的絕對值。所謂 n-1 階主?式,就是對于r(1≤r≤n),將 C[G]的第 r ?、第 r 列同時(shí)去掉后得到的新矩陣,? Cr[G]表示。
矩陣樹方法實(shí)現(xiàn):
實(shí)現(xiàn)方法很簡單,第一步是構(gòu)建拉氏矩陣,很簡單。難點(diǎn)在于實(shí)現(xiàn)求行列式的值。我這里采用矩陣初等變換將矩陣轉(zhuǎn)化為上三角矩陣,這樣行列式的值就等于主對角元素乘積。我實(shí)現(xiàn)了打印拉氏矩陣C和輸出圖生成樹個(gè)數(shù)這兩個(gè)方法,主體程序如下:
#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è)數(shù)為:" << G
.getTreeNum() << endl
; return 0;
}
運(yùn)行結(jié)果:
總結(jié)
以上是生活随笔為你收集整理的无向图生成树计数 -- Kirchhoff 矩阵法模板的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。