经典题目8

hdu  2157  How many ways??

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2157

题目大意:给定一个有向图,问从A点恰好走k步(允许重复经过边)到达B点的方案数mod p的值
把 给定的图转为邻接矩阵,即A(i,j)=1当且仅当存在一条边i->j。令C=A*A,那么C(i,j)=ΣA(i,k)*A(k,j),实际上就 等于从点i到点j恰好经过2条边的路径数(枚举k为中转点)。类似地,C*A的第i行第j列就表示从i到j经过3条边的路径数。同理,如果要求经过k步的 路径数,我们只需要二分求出A^k即可。

代码如下:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #define N 21
 4 #define M 1000
 5 struct Matrix
 6 {
 7     int edge[N][N];
 8 }map,res,tmp,map2;
 9 int n,m;
10 Matrix mul(Matrix x,Matrix y)  //矩阵连乘
11 {
12     int i,j,k;
13     memset(tmp.edge,0,sizeof(tmp.edge));
14     for(i=0;i<n;i++)
15         for(j=0;j<n;j++)
16             for(k=0;k<n;k++)
17             {
18                 tmp.edge[i][j]+=(x.edge[i][k]*y.edge[k][j])%M;
19                 tmp.edge[i][j]%=M;
20             }
21     return tmp;
22 }
23 void quickpow(int k)   //二进制思想
24 {
25     int i;
26     memset(res.edge,0,sizeof(res.edge));
27     for(i=0;i<n;i++)   //初始化为单位矩阵
28             res.edge[i][i]=1;
29     while(k)
30     {
31         if(k&1)
32             res=mul(res,map2);
33         map2=mul(map2,map2);
34         k>>=1;
35     }
36 }
37 int main()
38 {
39     int i,a,b,k,j,s,e,t;
40     while(scanf("%d%d",&n,&m)!=EOF)
41     {
42         if(n==0&&m==0)
43             break;
44         memset(map.edge,0,sizeof(map.edge));
45         for(i=0;i<m;i++)
46         {
47             scanf("%d%d",&a,&b);
48             map.edge[a][b]=1;
49         }
50         scanf("%d",&t);
51         while(t--)
52         {
53             scanf("%d%d%d",&s,&e,&k);
54             for(i=0;i<n;i++)
55                 for(j=0;j<n;j++)
56                     map2.edge[i][j]=map.edge[i][j];
57             quickpow(k);
58             printf("%d\n",res.edge[s][e]%M);
59         }
60     }
61     return 0;
62 }
View Code

相关文章:

  • 2021-12-13
  • 2021-09-02
  • 2020-04-07
  • 2021-11-05
  • 2022-01-28
  • 2022-12-23
  • 2022-02-02
猜你喜欢
  • 2021-09-27
  • 2021-06-22
  • 2021-12-19
  • 2021-10-21
  • 2022-01-31
  • 2021-06-07
  • 2021-08-06
相关资源
相似解决方案