suxxsfe

一言(ヒトコト)

P6178 【模板】Matrix-Tree 定理

https://www.luogu.com.cn/problem/P6178

矩阵树定理:https://oi-wiki.org/graph/matrix-tree/

对于存在重边的图,矩阵树定理也可以处理
考虑对于一种形态的生成树(一种形态就是说先把重边考虑为同一种边),重边使得他应该被计算 所以边重的次数的乘积 次
然后如果把边重的数量理解为边权,那么求出来的就是这种形态的树的边权乘积
那么整个矩阵树定理跑下来就是求出所有形态的生成树的边权乘积的和

于是这题就能做了

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
#define reg register
#define LL_INF (long long)(0x3f3f3f3f3f3f3f3f)
#define INT_INF (int)(0x3f3f3f3f)
inline int read(){
	register int x=0;register int y=1;
	register char c=std::getchar();
	while(c<'0'||c>'9'){if(c=='-') y=0;c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+(c^48);c=getchar();}
	return y?x:-x;
}
#define mod 1000000007
#define N 306
int n,m;
long long a[N][N];
inline long long det(){
	long long ans=1;
	for(reg int i=2;i<=n;i++){
		for(reg int j=i+1;j<=n;j++){
			if(a[j][i]>a[i][i]) std::swap(a[j],a[i]),ans=-ans;
			while(a[j][i]){
				long long k=a[i][i]/a[j][i];
				for(reg int h=2;h<=n;h++) a[i][h]=(a[i][h]+(mod-k)*a[j][h])%mod;
				std::swap(a[i],a[j]);
				ans=-ans;
			}
		}
	}
	for(reg int i=2;i<=n;i++) ans=ans*a[i][i]%mod;
	return (ans+mod)%mod;
}
int main(){
	n=read();m=read();int t=read();
	for(reg int u,v,w,i=1;i<=m;i++){
		u=read();v=read();w=read();
		if(t){
			a[u][v]=(a[u][v]+mod-w)%mod;
			a[v][v]=(a[v][v]+w)%mod;
		}
		else{
			a[u][v]=(a[u][v]+mod-w)%mod;a[v][u]=(a[v][u]+mod-w)%mod;
			a[u][u]=(a[u][u]+w)%mod;a[v][v]=(a[v][v]+w)%mod;
		}
	}
	printf("%lld\n",det());
	return 0;
}
posted @ 2021-03-10 20:00  suxxsfe  阅读(65)  评论(0编辑  收藏  举报