日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

无向图生成树计数 -- Kirchhoff 矩阵法模板

發(fā)布時(shí)間:2024/1/1 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 无向图生成树计数 -- Kirchhoff 矩阵法模板 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Kirchhoff 矩陣法是根據(jù)Matrix-Tree定理來(lái)的,本人太菜,沒(méi)有那個(gè)心力去看證明了,知道是用就可以了

作用:

給定一個(gè)n個(gè)點(diǎn)m條邊的無(wú)向圖,求出這個(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 階主?式的?列式的絕對(duì)值。所謂 n-1 階主?式,就是對(duì)于r(1≤r≤n),將 C[G]的第 r ?、第 r 列同時(shí)去掉后得到的新矩陣,? Cr[G]表示。

矩陣樹方法實(shí)現(xiàn):
實(shí)現(xiàn)方法很簡(jiǎn)單,第一步是構(gòu)建拉氏矩陣,很簡(jiǎn)單。難點(diǎn)在于實(shí)現(xiàn)求行列式的值。我這里采用矩陣初等變換將矩陣轉(zhuǎn)化為上三角矩陣,這樣行列式的值就等于主對(duì)角元素乘積。我實(shí)現(xiàn)了打印拉氏矩陣C和輸出圖生成樹個(gè)數(shù)這兩個(gè)方法,主體程序如下:

#include<bits/stdc++.h>using namespace std;class spanningTreeNum { private:int V = 0; // 頂點(diǎn)數(shù)vector<vector<int> > c; // 拉式矩陣c=d-A public:spanningTreeNum(int V){this->V = V;c = vector<vector<int> >(V, vector<int>(V, 0)); //初始化二維矩陣c為0}void addEdge(int u, int v); // u和v之間加一條邊int getTreeNum();int det(vector<vector<float> > A); // 求行列式A的值void showC(); };void spanningTreeNum::addEdge(int u, int v) {c[u][u]++; // 頂點(diǎn)度數(shù)加一c[v][v]++;c[u][v] = -1; // 表示頂點(diǎn)u、v之間有一條邊,因?yàn)閏=d-A,所以為-1c[v][u] = -1; }int spanningTreeNum::det(vector<vector<float> > A) {/** 思路是將利用初等變換A轉(zhuǎn)化為上三角矩陣,這樣對(duì)角線元素乘積即為行列式值*/float res = 1;int iter = 0; // 記錄交換次數(shù)for (int i = 0; i < A.size(); ++i) { //該for循環(huán)內(nèi)的邏輯是將矩陣轉(zhuǎn)化為上三角矩陣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(); //打印拉式矩陣Ccout << "生成樹個(gè)數(shù)為:" << G.getTreeNum() << endl; // 打印生成樹個(gè)數(shù)return 0; }

運(yùn)行結(jié)果:

總結(jié)

以上是生活随笔為你收集整理的无向图生成树计数 -- Kirchhoff 矩阵法模板的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。