HDU 2157 How many ways??:矩陣快速冪【i到j共經過k個節點的方法數】

Leohh發表於2017-08-18

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=2157

題解:

  給你一個有向圖,n個節點m條邊,問你從i到j共經過k個節點的方法數(不算i點)。

 

題解:

  先用鄰接矩陣存圖。

  假設k = 2,那麼從i到j的方法數 = ∑ way[i][x] * way[x][j] (0<=x<n && x!=i && x!=j)

  誒?快看,那是矩陣乘法!

  

  設鄰接矩陣為A,若i到j有邊則val[i][j] = 1。

  k = 2時答案矩陣ans是A^2,答案就是ans.val[i][j]。

  那k任意時,答案矩陣就是A^k,答案為ans.val[i][j]。

 

AC Code:

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #define MAX_L 25
  5 #define MOD 1000
  6 
  7 using namespace std;
  8 
  9 struct Mat
 10 {
 11     int n;
 12     int m;
 13     int val[MAX_L][MAX_L];
 14     Mat()
 15     {
 16         n=0;
 17         m=0;
 18         memset(val,0,sizeof(val));
 19     }
 20 };
 21 
 22 int n,m,t;
 23 int a,b,k;
 24 
 25 Mat make_unit(int n)
 26 {
 27     Mat mat;
 28     mat.n=n;
 29     mat.m=n;
 30     for(int i=0;i<n;i++)
 31     {
 32         mat.val[i][i]=1;
 33     }
 34     return mat;
 35 }
 36 
 37 Mat mul_mat(const Mat &a,const Mat &b)
 38 {
 39     Mat c;
 40     if(a.m!=b.n)
 41     {
 42         cout<<"Error: mul_mat"<<endl;
 43         return c;
 44     }
 45     c.n=a.n;
 46     c.m=b.m;
 47     for(int i=0;i<a.n;i++)
 48     {
 49         for(int j=0;j<b.m;j++)
 50         {
 51             for(int k=0;k<a.m;k++)
 52             {
 53                 c.val[i][j]+=a.val[i][k]*b.val[k][j];
 54                 c.val[i][j]%=MOD;
 55             }
 56         }
 57     }
 58     return c;
 59 }
 60 
 61 Mat quick_pow_mat(Mat mat,int k)
 62 {
 63     Mat ans;
 64     if(mat.n!=mat.m)
 65     {
 66         cout<<"Error: quick_pow_mat"<<endl;
 67         return ans;
 68     }
 69     ans=make_unit(mat.n);
 70     while(k)
 71     {
 72         if(k&1)
 73         {
 74             ans=mul_mat(ans,mat);
 75         }
 76         mat=mul_mat(mat,mat);
 77         k>>=1;
 78     }
 79     return ans;
 80 }
 81 
 82 int main()
 83 {
 84     while(cin>>n>>m)
 85     {
 86         if(n==0 && m==0) break;
 87         Mat start;
 88         start.n=n;
 89         start.m=n;
 90         for(int i=0;i<m;i++)
 91         {
 92             cin>>a>>b;
 93             start.val[a][b]=1;
 94         }
 95         cin>>t;
 96         for(int i=0;i<t;i++)
 97         {
 98             cin>>a>>b>>k;
 99             Mat ans=quick_pow_mat(start,k);
100             cout<<ans.val[a][b]<<endl;
101         }
102     }
103 }

 

相關文章