题面传送门
介绍一个结论:无向无权图的生成树个数是度数矩阵减去邻接矩阵去掉任意行列的行列式的值。
然后有权图就是将度数改为权值。
有向图的话需要考虑是内向树还是外向树,内向树每个点权值是出边,外向树是入边。
然后就可以开开心心\(O(n^3)\)了。
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define ll long long
#define db double
#define N 1000
#define M 5000
#define mod 1000000007
#define eps (1e-7)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
using namespace std;
int n,m,op,x,y,z;ll A[N+5][N+5],now,ans=1;
I void swap(ll &x,ll &y){x^=y^=x^=y;} 
I ll calc(){
	re int i,j,h;for(i=2;i<=n;i++){
		for(j=i+1;j<=n;j++){
			while(A[j][i]){
				now=mod-A[i][i]/A[j][i];for(h=i;h<=n;h++)A[i][h]=(A[i][h]+A[j][h]*now)%mod;
				for(h=i;h<=n;h++) swap(A[i][h],A[j][h]);ans*=-1;
			}
		}
	}for(i=2;i<=n;i++) ans=ans*A[i][i]%mod;return (ans%mod+mod)%mod;
}
int main(){
	freopen("1.in","r",stdin);
	re int i,j;scanf("%d%d%d",&n,&m,&op);while(m--){
		scanf("%d%d%d",&x,&y,&z);if(op==1)A[x][y]-=z,A[y][y]+=z;
		else A[x][x]+=z,A[x][y]-=z,A[y][x]-=z,A[y][y]+=z;
	} for(i=1;i<=n;i++) for(j=1;j<=n;j++) A[i][j]=(A[i][j]%mod+mod)%mod;printf("%lld\n",calc());
}