☆ [HDU2157] How many ways?? 「矩阵乘法求路径方案数」

传送门:>Here<

题意:给出一张有向图,问从点A到点B恰好经过k个点(包括终点)的路径方案数

解题思路

一道矩阵乘法的好题!妙哉~

话说把矩阵乘法放在图上好神奇,那么跟矩阵唯一有关的就是邻接矩阵……

考虑邻接矩阵在这道题里的含义也就是从A到B经过1个点的方案数——能到达或不能到达。而当邻接矩阵自乘时,假设自乘一次得到矩阵B,则$b[i][j] = \sum\limits_{}{}g[i][k]*g[k][j]$。因此k就作为了枚举的中介点,由于最后得到的项是累积的,所以自乘一次以后就得到了经过2个点的方案数。因此自乘k-1即能得到经过k个点的方案数。

此时,乘法的意义就成为了每一次累积$(i->k)的方案数 * (k->j)的方案数 \  (起点终点固定)$ 

Code

/*By DennyQi*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define  r  read()
#define  Max(a,b)  (((a)>(b)) ? (a) : (b))
#define  Min(a,b)  (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int MAXN = 10010;
const int MAXM = 27010;
const int INF = 1061109567;
inline int read(){
    int x = 0; int w = 1; register int c = getchar();
    while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
    if(c == '-') w = -1, c = getchar();
    while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar(); return x * w;
}
int N,M,K,Q,x,y,A,B;
int g[30][30],a[30][30],b[30][30],ans[30][30][30];
inline void Init(){
    memset(g, 0, sizeof(g));
}
inline void Matrix_mul(){
    memset(ans, 0, sizeof(ans));
    for(int num = 0; num <= 20; ++num){
        for(int i = 1; i <= N; ++i){
            ans[num][i][i] = 1;
        }
    }
    for(int num = 1; num <= 20; ++num){
        for(int i = 1; i <= N; ++i){
            for(int j = 1; j <= N; ++j){
                b[i][j] = 0;
                for(int k = 1; k <= N; ++k){
                    b[i][j] = (b[i][j] + ans[num-1][i][k] * g[k][j]) % 1000;
                }
            }
        }
        for(int i = 1; i <= N; ++i){
            for(int j = 1; j <= N; ++j){
                ans[num][i][j] = b[i][j];
            }
        }
    }
}
int main(){
    for(;;){
        N = r, M = r;
        if(!N && !M) break;
        Init();
        for(int i = 1; i <= M; ++i){
            x = r+1, y = r+1;
            g[x][y] = 1;
        }
        Matrix_mul();
        Q = r;
        while(Q--){
            A = r, B = r, K = r;
            printf("%d\n", ans[K][A+1][B+1] % 1000);
        }
    }
    return 0;
}

 

posted @ 2018-08-07 16:49  DennyQi  阅读(474)  评论(0编辑  收藏  举报