【BZOJ3659】Which Dreamed It【有向圖歐拉回路計數】【matrix tree定理】【BEST定理】【高斯消元】
阿新 • • 發佈:2019-01-07
定理題...
/* Think Thank Thunk */ #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int maxn = 105, p = 1000003; int n, fact[200005], A[maxn][maxn], du[maxn]; inline int iread() { int f = 1, x = 0; char ch = getchar(); for(; ch < '0' || ch > '9'; ch = getchar()) f = ch == '-' ? -1 : 1; for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0'; return f * x; } inline int qpow(int a, int n) { int res = 1; for(; n; n >>= 1, a = (LL)a * a % p) if(n & 1) res = (LL)res * a % p; return res; } inline int gauss() { for(int i = 1; i < n; i++) { if(!A[i][i]) for(int j = i + 1; j < n; j++) if(A[j][i]) { for(int k = i; k < n; k++) swap(A[i][k], A[j][k]); break; } int rev = qpow(A[i][i], p - 2); for(int j = i + 1; j < n; j++) if(A[j][i]) { int t = (LL)A[j][i] * rev % p; for(int k = i; k < n; k++) A[j][k] = (A[j][k] - (LL)A[i][k] * t % p + p) % p; } } int res = 1; for(int i = 1; i < n; i++) res = (LL)res * A[i][i] % p; return res; } int main() { fact[0] = 1; for(int i = 1; i <= 200000; i++) fact[i] = (LL)fact[i - 1] * i % p; while(1) { n = iread(); if(!n) break; for(int i = 1; i <= n; i++) { du[i] = 0; for(int j = 1; j <= n; j++) A[i][j] = 0; } for(int i = 1; i <= n; i++) { du[i] = iread(); for(int j = 1; j <= du[i]; j++) { int x = iread(); if(x != i) A[i][x]--, A[i][i]++; } } if(n == 1 && du[1] == 0) { printf("1\n"); continue; } for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) (A[i][j] += p) %= p; int ans = (LL)gauss() * du[1] % p; for(int i = 1; i <= n; i++) ans = (LL)ans * fact[du[i] - 1] % p; printf("%d\n", ans); } return 0; }