Solution
(BEST) 定理,套用完成后,由于每一个路径都对应了 (deg_1) 这么多的不同起始方向的情况数,乘上去就可以了。
Code
#include<bits/stdc++.h>
using namespace std;
inline void read (int&a)
{
a = 0; char k = getchar(); int f = 1;
while (k > '9' || k < '0') { if (k == '0') f = -1; k = getchar(); }
while (k >= '0' && k <= '9') { a = a * 10 + k - '0'; k = getchar (); }
a *= f;
}
const int N = 200 + 5, mod = 1000003;
inline int plu (int u, int v) { return u + v >= mod ? u + v - mod : u + v; }
inline int sub (int u, int v) { return u - v < 0 ? u - v + mod : u - v; }
inline int mul (int u, int v) { return 1LL * u * v % mod; }
int a[N][N], n, outdeg[N], indeg[N], fac[200000 + 5];
inline int Guass ()
{
// for (int i = 1; i <= n; ++i, puts (""))
// for (int j = 1; j <= n; ++j)
// printf ("%d ", a[i][j]);
int ans = 1;
for (int i = 1; i <= n - 1; ++i)
{
for (int j = i + 1; j <= n - 1; ++j)
{
while (a[j][i])
{
int l = a[i][i] / a[j][i];
for (int k = i; k <= n - 1; ++k)
a[i][k] = sub (a[i][k], mul (l, a[j][k]));
swap (a[i], a[j]);
ans = mod - ans;
}
}
ans = mul (ans, a[i][i]);
}
return ans;
}
int main ()
{
fac[0] = 1;
for (int i = 1; i <= 200000; ++i)
fac[i] = 1LL * fac[i - 1] * i % mod;
while (scanf ("%d", &n) == 1 && n)
{
memset (a, 0, sizeof a);
memset (outdeg, 0, sizeof outdeg);
memset (indeg, 0, sizeof indeg);
for (int i = 1; i <= n; ++i)
{
int s; read (s);
for (int j = 1; j <= s; ++j)
{
int k; read (k);//i -> k
a[i][k]--;
a[i][i]++;
indeg[k]++;
outdeg[i]++;
}
}
if (n == 1) { printf ("%d
", fac[ indeg[1] ]); continue; }//不用特判也可以过
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j)
a[i][j] = sub (a[i][j], 0);
bool flag = false;
for (int i = 1; i <= n; ++i)
if (indeg[i] != outdeg[i])
{ printf ("0
"), flag = true; break; }
if (flag) continue;
int ans = 1;
for (int i = 1; i <= n; ++i)
ans = mul (ans, fac[ indeg[i] - 1 ]);
ans = mul (ans, mul (Guass(), indeg[1]));
printf ("%d
", ans);
}
return 0;
}
Conclusion
又开始错各种细节了。
比如矩阵忘了去掉某一行,而是直接 (n) 行计算。
注意某一行我写了不用特判也可以,因为高斯消元里面返回的因该是 (1) 。