3659: Which Dreamed It
Time Limit: 20 Sec Memory Limit: 1024 MBSubmit: 172 Solved: 49
[Submit][Status][Discuss]
Description
有n个房间,每个房间有若干把钥匙能够打开特定房间的门。
你会做这么件事情:
最初你在房间1。
每当你到达一个房间,你可以选择该房间的一把钥匙,前往该钥匙对
应的房间,并将该钥匙丢到垃圾桶中。
你希望:最终回到房间1,且垃圾桶中有所有的钥匙。
求方案数。两组方案不同,当且仅当使用钥匙的顺序不同。注意,每
把钥匙都是不同的。
Input
有多组数据。
对于每组数据第一行输入一个数n,表示房间数。
接下来n行依次描述每个房间:
首先一个数s,表示这个房间的钥匙数目,接下来s个数,分别描述每把
钥匙能够打开的房间的门。
输入以n-0结尾。
Output
对于每组数据,输出方案数,为了方便你的输出,请将答案对1000003取模。
Sample Input
1
0
2
1 1
1 2
0
0
2
1 1
1 2
0
Sample Output
1
0
0
HINT
在第一组样例中,没有钥匙,则方案数为1。
在第二组样例中,你不可能使用第二个房间的钥匙,所以方案数为0。
房间数小于等于100,钥匙数小于等于200000。
数据组数也不是特别多。
定理题 这定理命名就是最大的槽点
Best Theorem
以某个点为起点的欧拉回路数=该点为根的树形图数*((每个点出度-1 )的阶乘)
这个题再多乘一个d[1]因为不同点出发算不同方案
基尔霍夫矩阵适用于有向图 度数矩阵存出度 邻接矩阵正常搞
重边不怕照样好使 自环删掉 找搞不误
这是今天最后一道矩阵树定理了 吧。。。。
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}
const int N=110,mod=1000003;
int a[N][N],d[N],fac[mod];
void initial()
{memset(a,0,sizeof(a));memset(d,0,sizeof(d));}
int det(int n)
{
register int i,j,k,res=1,x,y,tmp,f=1;
for(i=1;i<=n;++i)for(j=1;j<=n;++j)a[i][j]=(a[i][j]+mod)%mod;
for(i=1;i<=n;++i)
{
for(j=i+1;j<=n;++j)
{
x=a[i][i],y=a[j][i];
while(y)
{
tmp=x/y;x%=y;swap(x,y);
for(k=i;k<=n;++k)
a[i][k]=((a[i][k]-1ll*tmp*a[j][k])%mod+mod)%mod;
for(k=i;k<=n;++k)swap(a[i][k],a[j][k]);
f=-f;
}
}
if(!a[i][i])return 0;
res=1ll*res*a[i][i]%mod;
}
if(f==-1)res=mod-res;
return (res%mod+mod)%mod;
}
int main()
{
register int i,j,v,n=read(),ans;
fac[0]=1;for(i=1;i<mod;++i)fac[i]=1ll*fac[i-1]*i%mod;//cout<<n<<endl;
while(n)
{
ans=1;
for(i=1;i<=n;++i)
{
d[i]=read();
for(j=1;j<=d[i];++j){v=read();if(i!=v)a[i][i]++,a[i][v]--;}
}
if(n==1&&!d[1]){puts("1");n=read();continue;}
for(i=1;i<=n;++i)ans=1ll*ans*fac[d[i]-1]%mod;
ans=1ll*ans*det(n-1)%mod;ans=1ll*ans*d[1]%mod;
print(ans);puts("");
n=read();initial();
}
return 0;
}
/*
1
0
2
1 1
1 2
0
1
0
*/