• 【BZOJ 3659】 3659: Which Dreamed It (Matrix-Tree&BEST theorem )


    3659: Which Dreamed It

    Time Limit: 20 Sec  Memory Limit: 1024 MB
    Submit: 134  Solved: 41

    Description

    有n个房间,每个房间有若干把钥匙能够打开特定房间的门。
    你会做这么件事情:
    最初你在房间1。
    每当你到达一个房间,你可以选择该房间的一把钥匙,前往该钥匙对
    应的房间,并将该钥匙丢到垃圾桶中。
    你希望:最终回到房间1,且垃圾桶中有所有的钥匙。
    求方案数。两组方案不同,当且仅当使用钥匙的顺序不同。注意,每
    把钥匙都是不同的。

    Input

     有多组数据。
    对于每组数据第一行输入一个数n,表示房间数。
    接下来n行依次描述每个房间:
    首先一个数s,表示这个房间的钥匙数目,接下来s个数,分别描述每把
    钥匙能够打开的房间的门。
    输入以n-0结尾。

    Output

    对于每组数据,输出方案数,为了方便你的输出,请将答案对1000003取模。

    Sample Input

    1
    0
    2
    1 1
    1 2
    0

    Sample Output

    1
    0

    HINT

    在第一组样例中,没有钥匙,则方案数为1。

    在第二组样例中,你不可能使用第二个房间的钥匙,所以方案数为0。







    房间数小于等于100,钥匙数小于等于200000。

    数据组数也不是特别多。

    Source

    【分析】

      这种题叫做结论题。

      %CA爷

      然后这里有两个结论 
      1.有向图以i为根的树形图的数目=基尔霍夫矩阵去掉第i行和第i列的主子式的行列式的值(即Matrix-Tree定理不仅适用于求无向图生成树数目,也适用于求有向图树形图数目) 
      2.以某个点为起点的欧拉回路数=该点为根的树形图数*(所有点出度-1)的乘积(本名BEST theorem) 
      关于BEST theorem可以提供一个wiki上的讲解:about BEST theorem 

      最后还有乘上起点的出度?【怎么没说。。

    【我觉得我Mod那里应该有问题,但是我没有被卡哦。。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 using namespace std;
     7 #define LL long long
     8 const int Mod=1000003;
     9 #define Maxn 1000010
    10 
    11 int a[110][110],m[110],fac[Maxn];
    12 
    13 int qpow(int x,int b)
    14 {
    15     x%=Mod;
    16     int ans=1;
    17     while(b)
    18     {
    19         if(b&1) ans=1LL*ans*x%Mod;
    20         x=1LL*x*x%Mod;
    21         b>>=1;
    22     }
    23     return ans;
    24 }
    25 
    26 int gauss(int n)
    27 {
    28     if (n==0) return 1;
    29     int ans=1;
    30     for(int i=1;i<=n;i++)
    31     {
    32         int t=i;
    33         for(int j=i+1;j<=n;j++) if(a[j][i]>a[t][i]) t=j;
    34         if(a[t][i]==0) return 0;
    35         if(t!=i)
    36         {
    37             ans=-ans;
    38             for(int j=1;j<=n;j++) swap(a[t][j],a[i][j]);
    39         }
    40         int ny=qpow(a[i][i],Mod-2);
    41         for(int j=i+1;j<=n;j++)
    42         {
    43             int nw=1LL*ny*a[j][i]%Mod;
    44             for(int k=i;k<=n;k++) a[j][k]-=1LL*a[i][k]*nw%Mod,a[j][k]=(a[j][k]%Mod+Mod)%Mod;
    45         }
    46     }
    47     for(int i=1;i<=n;i++) ans=1LL*ans*a[i][i]%Mod;
    48     ans=(ans%Mod+Mod)%Mod;
    49     return ans;
    50 }
    51 
    52 int main()
    53 {
    54     int n;
    55     fac[0]=1;for(int i=1;i<=Mod;i++) fac[i]=1LL*fac[i-1]*i%Mod;
    56     while(1)
    57     {
    58         scanf("%d",&n);
    59         if(!n) break;
    60         memset(a,0,sizeof(a));
    61         for(int i=1;i<=n;i++)
    62         {
    63             scanf("%d",&m[i]);
    64             for(int j=1;j<=m[i];j++)
    65             {
    66                 int x;
    67                 scanf("%d",&x);
    68                 if(i!=x) a[i][x]--,a[i][i]++;
    69             }
    70         }
    71         if(n==1&&!m[1]) {printf("1
    ");continue;}
    72         int ans=1;
    73         for(int i=1;i<=n;i++) ans=1LL*ans*fac[m[i]-1]%Mod;
    74         ans=1LL*ans*m[1]%Mod;
    75         ans=1LL*ans*gauss(n-1)%Mod;
    76         printf("%d
    ",ans);
    77     }
    78     return 0;
    79 }
    View Code

    2017-04-16 20:11:07

  • 相关阅读:
    oracle12 安装
    ORACLE重装之后恢复数据库,相当于sqlserver的附加数据库
    git
    P1323 删数游戏(技巧)
    P2486 【SDOI2011】 染色
    P1084 【NOIP 2012】 疫情控制
    前缀、中缀、后缀表达式
    【P1979】 NOIP2013 华容道
    P2601 【ZJOI2009】对称的正方形
    NOIP2015 运输计划
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6719773.html
Copyright © 2020-2023  润新知