BZOJ4894 天赋

Description

小明有许多潜在的天赋,他希望学习这些天赋来变得更强。正如许多游戏中一样,小明也有n种潜在的天赋,但有
一些天赋必须是要有前置天赋才能够学习得到的。也就是说,有一些天赋必须是要在学习了另一个天赋的条件下才
能学习的。比如,要想学会"开炮",必须先学会"开枪"。一项天赋可能有多个前置天赋,但只需习得其中一个就可
以学习这一项天赋。上帝不想为难小明,于是小明天生就已经习得了1号天赋-----"打架"。于是小明想知道学习完
这n种天赋的方案数,答案对1,000,000,007取模。

Input

第一行一个整数n。
接下来是一个n*n的01矩阵,第i行第j列为1表示习得天赋j的一个前置天赋为i。
数据保证第一列和主对角线全为0。
n<=300

Output

第一行一个整数,问题所求的方案数。

Sample Input

8
01111111
00101001
01010111
01001111
01110101
01110011
01111100
01110110

Sample Output

72373

这题求的是有向图的生成数计数

转化一下,邻接矩阵只计出边,度数矩阵只计入边

但是不同的是,去掉i行i列求的是以i为根的有向生成树

所以只能去掉第1行第1列

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 typedef long long lol;
 8 int a[301][301],Mod=1e9+7,n,ans;
 9 char s[301][301];
10 void guass()
11 {int i,j,k;
12   n--;
13   ans=1;
14   for (i=1;i<=n;i++)
15     {
16       for (j=1;j<=n;j++)
17     {
18       a[i][j]=(a[i][j]+Mod)%Mod;
19     }
20     }
21   for (i=1;i<=n;i++)
22     {
23       for (j=i+1;j<=n;j++)
24     {
25       while (a[j][i])
26         {
27           int t=a[i][i]/a[j][i];
28           for (k=i;k<=n;k++)
29         {
30           a[i][k]=(a[i][k]-1ll*t*a[j][k]%Mod+Mod)%Mod;
31           swap(a[i][k],a[j][k]);
32         }
33           ans*=-1;
34         }
35     }
36       ans=1ll*ans*a[i][i]%Mod;
37     }
38   ans=(ans+Mod)%Mod;
39 }
40 int main()
41 {int i,j;
42   cin>>n;
43   for (i=0;i<n;i++)
44     {
45       scanf("%s",s[i]);
46     }
47   for (i=0;i<n;i++)
48     {
49       for (j=0;j<n;j++)
50     {
51       if (s[i][j]=='1')
52         a[i][j]--;
53     }
54       for (j=0;j<n;j++)
55     {
56       if (s[j][i]=='1')
57         a[i][i]++;
58     }
59     }
60   guass();
61   cout<<ans;
62 }

 

posted @ 2018-03-16 19:42  Z-Y-Y-S  阅读(226)  评论(0编辑  收藏  举报