【題目描述】
給你乙個n個點,m條邊的無向圖,求其生成樹個數。(1<=n<=12)
【分析】
由於原問題規模較小,可以使用複雜度較高的演算法,如指數級的動態規劃。
那麼如果n=1000呢?
【基爾霍夫矩陣】
對於無向圖,它的kirchhoff矩陣定義為度數矩陣減去鄰接矩陣。
在計算時,用a表示kirchhoff矩陣。則:
當i==j時,a[i][j]=i的度數。
當i!=j時,i到j有k條邊相連時,a[i][j]=-k (沒有邊相連為0)
例如下圖
它的kirchhoff矩陣為
【matrix-tree定理】
對於乙個無向圖g,它的生成樹個數等於其kirchhoff矩陣任何乙個n-1階主子式的行列式的絕對值。
所謂n-1階主子式,就是對於任意乙個r,將c的第r行和第r列同時刪去後的新矩陣,用cr表示。
【行列式的計算】
首先有幾點性質:
1、矩陣的某一行同時除以某個數,行列式的值不變。
2、矩陣的某兩行相交換,行列式的值取相反數。
那麼我們可以通過這些性質,把原矩陣化為三角形矩陣。則行列式的值就等於對角線上值得乘積。(從左上到右下的對角線)
1附spoj104**:double sum=1
; 2
for(int i=1;i<=n-1;i++)313
if(!flag) return0;
14}15 sum*=a[i][i];
16for(int j=i+1;j<=n-1;j++) a[i][j]/=a[i][i];
17for(int j=i+1;j<=n-1;j++)
18for(int k=i+1;k<=n-1;k++)
19 a[j][k]-=a[i][k]*a[j][i];20}
21return sum;
就是多組資料而已。。。
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8using
namespace
std;
9#define maxn 101
10int n,m,t,map[maxn][maxn]; //
map表示鄰接矩陣,a表示基爾霍夫矩陣
11double
a[maxn][maxn];
12namespace
init
1316 inline int
read()
1720
while(isdigit(ch))
21return x*f;22}
23 }using
namespace
init;
24double
work()
2538
if(!flag) return0;
39}40 sum*=a[i][i];
41for(int j=i+1;j<=n-1;j++) a[i][j]/=a[i][i];
42for(int j=i+1;j<=n-1;j++)
43for(int k=i+1;k<=n-1;k++)
44 a[j][k]-=a[i][k]*a[j][i];45}
46if(sign&1) sum=-sum;
47return
sum;48}
49int
main()
5062
for(int i=1;i<=n;i++)
6369
for(int i=1;i<=n;i++)
70for(int j=1;j<=n;j++)
71if(map[i][j]) a[i][j]=-1;72
double ans=work();
73 printf("
%0.0lf\n
",ans);74}
75return0;
76 }
生成樹計數問題的簡單推廣
第乙個推廣 在生成樹計數問題中,其實我們做了這樣乙個假設,就是每條邊的權值是1。我們再來看下這個公式 對於關聯矩陣b來說 對於乙個n個頂點m條邊的無向圖g,它的關聯矩陣b是乙個n m的矩陣。對於第i條邊e i u,v 那麼b u i 和b v i 中乙個是1,乙個是 1,第i列其他值為0 我們可以這...
計數問題(二)
計數問題 二 在上一講中,我們一起研究 列舉法 乘法原理 加法原理 在計數問題中的應用。但是,在實際的問題中,這些方法並不是單獨使用的。往往需要同時應用這幾種方法,這就需要我們搞清題意,根據已知條件,分別使用正確的方法,得到準確的結果。一 閱讀思考 例1.求720這個數約數的個數。分析與解 從1開始...
問題 E 計數問題
時間限制 1 sec 記憶體限制 128 mb 提交 30 解決 22 提交狀態 討論版 命題人 admin 題目描述 試計算在區間 1 到 n 的所有整數中,數字 x 0 x 9 共出現了多少次?例如,在 1 到 11 中,即在 1 2 3 4 5 6 7 8 9 10 11 中,數字 1 出現了...