2018.10.28【CQOI2018】【洛谷P4455】【BZOJ5297】社交网络(有向图矩阵树)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/83479074

BZOJ传送门

洛谷传送门


解析:

其实 K i r c h o f f Kirchoff 的无向图矩阵本来就是有向图矩阵的一个扩展。所以这里仅将有向图的 K i r c h o f f Kirchoff 矩阵作一个简单的阐述,详细证明请参考其他 d a l a o dalao 的博客。(才不是因为我看网上证明都这么多了懒得写呢)

一条有向边 < u , v > <u,v> K i r c h o f f Kirchoff 矩阵上我们将 C v , v C_{v,v} 加1,因为这是入度,并且在 C v , u C_{v,u} 上减一。

最后我们要计算的是以某个节点为根的树形图的个数,我们将这个节点编号的一行一列去掉,计算剩余部分的行列式就行了。

其实会了这道题再回去看无向图的 M a t r i x T r e e Matrix Tree 定理就觉得一切都明白了许多。

所以这里为了方便,将所有节点编号-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;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/83479074
今日推荐