日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

發布時間:2024/1/1 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 无向图生成树计数 -- 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; // 拉式矩陣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]++; // 頂點度數加一c[v][v]++;c[u][v] = -1; // 表示頂點u、v之間有一條邊,因為c=d-A,所以為-1c[v][u] = -1; }int spanningTreeNum::det(vector<vector<float> > A) {/** 思路是將利用初等變換A轉化為上三角矩陣,這樣對角線元素乘積即為行列式值*/float res = 1;int iter = 0; // 記錄交換次數for (int i = 0; i < A.size(); ++i) { //該for循環內的邏輯是將矩陣轉化為上三角矩陣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.getTreeNum() << endl; // 打印生成樹個數return 0; }

運行結果:

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。