2018.10.28【CQOI2018】【洛谷P4455】【BZOJ5297】社交網路(有向圖矩陣樹)
阿新 • • 發佈:2019-02-03
洛谷傳送門
解析:
其實的無向圖矩陣本來就是有向圖矩陣的一個擴充套件。所以這裡僅將有向圖的矩陣作一個簡單的闡述,詳細證明請參考其他的部落格。(才不是因為我看網上證明都這麼多了懶得寫呢)
一條有向邊在矩陣上我們將加1,因為這是入度,並且在上減一。
最後我們要計算的是以某個節點為根的樹形圖的個數,我們將這個節點編號的一行一列去掉,計算剩餘部分的行列式就行了。
其實會了這道題再回去看無向圖的定理就覺得一切都明白了許多。
所以這裡為了方便,將所有節點編號-1,算出矩陣去掉第0行再計算行列式就行了。
由於是求模意義下的,所以要採用歐幾里得迭代法來實現高斯消元,將原矩陣消成上三角矩陣。
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
cs int mod=10007,N=251;
struct matrix{
int arr[N][N];
int *cs operator[](cs int &offset){
return arr[offset];
}
int matrix_tree(int n){
for(int re i=1;i<=n;++i)
for(int re j=1;j<=n;++j)arr[i][j]=(arr[i][j]%mod+mod)%mod;
int res=1;
for(int re i=1;i<=n;++i){
for(int re j=i+1;j<=n;++j){
while(arr[j][i]){
int tmp=arr[i][i]/arr[j][i];
for(int re k=i;k<=n;++k)arr[i][k]=(arr[i][k]-arr[j][k]*tmp%mod+mod)%mod;
for(int re k=i;k<=n;++k)swap(arr[i][k],arr[j][k]);
res=mod-res;
}
}
res=(res*arr[i][i])%mod;
}
return res;
}
}C;
int n,m;
signed main(){
n=getint();
m=getint();
for(int re i=1;i<=m;++i){
int v=getint()-1;
int u=getint()-1;
++C[v][v];
--C[v][u];
}
cout<<C.matrix_tree(n-1);
return 0;
}