【模版】生成樹計數
阿新 • • 發佈:2020-08-07
無向圖生成樹計數(取模)
- 圖中節點的下標從0開始計數!
- 不存在生成樹返回-1
- 不存在自環,允許存在重邊
typedef long long ll; const ll mod = 998244353; const int N = 105; const int M = 1e4 + 5; ll inv(ll a) { if(a == 1)return 1; return inv(mod%a)*(mod-mod/a)%mod; } struct Matrix { ll mat[N][N]; void init() { memset(mat,0,sizeof(mat)); } void addEdge(int u,int v) { mat[u][v]--; mat[u][u]++; } ll det(int n) { //求行列式的值模上MOD,需要使用逆元 for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) mat[i][j] = (mat[i][j]%mod+mod)%mod; ll res = 1; for(int i = 0; i < n; i++) { for(int j = i; j < n; j++) if(mat[j][i]!=0) { for(int k = i; k < n; k++) swap(mat[i][k],mat[j][k]); if(i != j) res = (-res+mod)%mod; break; } if(mat[i][i] == 0) { res = -1;//不存在(也就是行列式值為0) break; } for(int j = i+1; j < n; j++) { //int mut = (mat[j][i]*INV[mat[i][i]])%MOD;//打表逆元 ll mut = (mat[j][i]*inv(mat[i][i]))%mod; for(int k = i; k < n; k++) mat[j][k] = (mat[j][k]-(mat[i][k]*mut)%mod+mod)%mod; } res = (res * mat[i][i])%mod; } return res; } }ret;
呼叫:
ret.init();
for (int i = 1; i <= m; i++) {
scanf("%d%d%lld", &e[i].u, &e[i].v, &e[i].w);
ret.addEdge(--e[i].u, --e[i].v);
ret.addEdge(e[i].v, e[i].u);
}
ll tot = ret.det(n-1);
if(tot == -1) {
puts("0");
continue;
}