zoukankan      html  css  js  c++  java
  • HDU 2157 How many ways??:矩阵快速幂【i到j共经过k个节点的方法数】

    题目链接: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 }
  • 相关阅读:
    Android笔记之spinner的使用
    Android笔记之AlertDialog使用
    Android笔记之intent使用(一)
    Android笔记之Editext使用
    Android控件之Textiew的使用
    Fastboot常用命令集,完美取代Recovery的所有功能
    Android笔记之WebView
    Android程序下重启手机
    Android笔记之ListView组件的使用
    intellij idea设置(字体大小、背景)
  • 原文地址:https://www.cnblogs.com/Leohh/p/7392670.html
Copyright © 2011-2022 走看看