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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

P6178-[模板]Matrix-Tree 定理

發布時間:2023/12/3 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P6178-[模板]Matrix-Tree 定理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

題目鏈接:https://www.luogu.com.cn/problem/P6178


題目大意

給出一個nnn個點mmm條邊的無向/有向圖。

求所有的生成樹/以1為根的外向生成樹的權值乘積和。


解題思路

矩陣AAA的行列式表示為det(A)det(A)det(A),定義為
det(A)=∑P(?1)μ(P)∏i=1nAi,pidet(A)=\sum_P(-1)^{\mu(P)}\prod_{i=1}^nA_{i,p_i}det(A)=P?(?1)μ(P)i=1n?Ai,pi??
其中PPP是一個1~n1\sim n1n的排列,μ(P)\mu(P)μ(P)表示排列PPP的逆序對數量

即每一行選擇一個數乘起來,容斥系數與排列逆序對數量有關

我們需要解決的問題是如何快速求出一個矩陣的行列式,考慮如果對于所有行iii都滿足i+1~ni+1\sim ni+1n都沒有值,那么此時有det(A)=∏i=1nAi,idet(A)=\prod_{i=1}^nA_{i,i}det(A)=i=1n?Ai,i?。這個很容易理解,因為如果一行選擇的不是iii,那么一定存在有一行jjj的選擇大于jjj,那么此時這個方案的權值就為000了。

那么我們需要將一個矩陣變換成一個行列式不變的上三角矩陣,這里需要用到行列式的初等變換

  • 若交換兩行,那么行列式。因為交換后原來權值相同的容斥系數都會變化,所以值取反。
  • [a+x,b+yc,d]=[a,bc,d]+[x,yc,d]\begin{bmatrix}a+x,b+y\\c,d\end{bmatrix}=\begin{bmatrix}a,b\\c,d\end{bmatrix}+\begin{bmatrix}x,y\\c,d\end{bmatrix}[a+x,b+yc,d?]=[a,bc,d?]+[x,yc,d?]乘法分配率可得
  • 若有兩行完全相同,那么這個行列式為000。證明方法是交換這兩行后矩陣不變理論上行列式也不便,但是行列式取反了,也就是原行列式為000
  • 若讓一行加上另一行那么行列式不變,證明的話[a,ba,b]=0\begin{bmatrix}a,b\\a,b\end{bmatrix}=0[a,ba,b?]=0 [a,ba+c,b+d]=[a,ba,b]+[a,bc,d]=[a,bc,d]\begin{bmatrix}a,b\\a+c,b+d\end{bmatrix}=\begin{bmatrix}a,b\\a,b\end{bmatrix}+\begin{bmatrix}a,b\\c,d\end{bmatrix}=\begin{bmatrix}a,b\\c,d\end{bmatrix}[a,ba+c,b+d?]=[a,ba,b?]+[a,bc,d?]=[a,bc,d?]
  • 然后這樣就可以用高斯消元的方法消矩陣了,然后就可以求出行列式了。

    回到這題來,矩陣樹定理大體來說就是,AAA表示一張無向圖的鄰接矩陣,DDD表示度數矩陣(Di,iD_{i,i}Di,i?iii的度數,其他為000)。去掉DDDAAA的第kkk行和第kkk列之后就有det(D?A)det(D-A)det(D?A)就表示這張圖的生成樹個數。

    當然有向圖也可以,如果是外向樹,那么DDD表示入度矩陣,內向就是出度矩陣,若xxx為根,去掉第xxx行第xxx列之后det(D?A)det(D-A)det(D?A)就是答案了。

    這里是求權值乘積和,重邊數等于權值就好了。

    時間復雜度O(n3)O(n^3)O(n3)


    codecodecode

    #include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=310,P=1e9+7; ll n,m,t,ans,a[N][N]; ll power(ll x,ll b){ll ans=1;while(b){if(b&1)ans=ans*x%P;x=x*x%P;b>>=1;}return ans; } void dec(){ll f=1;ans=1;for(ll i=2;i<=n;i++){ll w=i;for(ll j=i;j<=n;j++)if(a[i][j]){if(i!=j)f=-f;w=j;break;}swap(a[i],a[w]);ll inv=power(a[i][i],P-2);ans=ans*a[i][i]%P;if(!a[i][i])return;for(ll j=i;j<=n;j++)a[i][j]=a[i][j]*inv%P;for(ll j=i+1;j<=n;j++){ll rate=P-a[j][i];for(ll k=i;k<=n;k++)a[j][k]=(a[j][k]+rate*a[i][k]%P+P)%P;}}ans=ans*f;return; } int main() {scanf("%lld%lld%lld",&n,&m,&t);for(ll i=1;i<=m;i++){ll x,y,w;scanf("%lld%lld%lld",&x,&y,&w);if(t)a[y][y]=(a[y][y]+w)%P,a[x][y]=(a[x][y]-w)%P;else a[x][x]=(a[x][x]+w)%P,a[y][y]=(a[y][y]+w)%P,a[x][y]=(a[x][y]-w)%P,a[y][x]=(a[y][x]-w)%P;}dec();printf("%lld\n",(ans+P)%P); }

    總結

    以上是生活随笔為你收集整理的P6178-[模板]Matrix-Tree 定理的全部內容,希望文章能夠幫你解決所遇到的問題。

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