How many ways??---hdu2157(矩阵快速幂)

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

 

题意:有一个有向图,含有n个节点,m条边,Q个询问,每个询问有 s,t,p,求 s 到 t 经过 p  个点(这 p 个点包括 t 点,不包括 s 点)的所有方案数对100求余; 

 

我们知道floyd算法中(i, j)是可以由(i,k)和(k,j)得到;那么就是经过k这个中间节点;这样一来就是 i -- k -- j  经过两个节点(k,j)所以从 i 到 j 经过2个点的方案总数是  (i,j)= ∑(i,k)*(k,j);(枚举所有的

k )然而这个正是矩阵(A*A)相乘的结果

以此类推经过3个点,4个点...p个点所求就是A^p中的(s, t);

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <map>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;

#define N 50
#define MOD 1000
#define met(a, b) memset(a, b, sizeof(a))
#define INF 0x3f3f3f3f

typedef long long LL;

struct Matrix
{
    int a[N][N];
    Matrix()
    {
        memset(a, 0, sizeof(a));///注意初始化;
    }
};

int n, m;

Matrix Mul(Matrix p, Matrix q)
{
    Matrix temp;///注意初始化;

    for(int i=0; i<n; i++)
    {
        for(int j=0; j<n; j++)
        {
            for(int k=0; k<n; k++)
                temp.a[i][j] = (temp.a[i][j] + p.a[i][k]*q.a[k][j]) % MOD;
        }
    }
    return temp;
}


Matrix Pow(Matrix Matrix0, int k)
{
    Matrix temp, Matrix1 = Matrix0;

    for(int i=0; i<N; i++)
        temp.a[i][i] = 1;///注意初始化;

    while(k)
    {
        if(k%2 == 1)
            temp = Mul(temp, Matrix1);
        Matrix1 = Mul(Matrix1, Matrix1);
        k /= 2;
    }
    return temp;
}


int main()
{
    int u, v, k, Q;

    while(scanf("%d %d", &n, &m), m+n)
    {
        Matrix Matrix0;

        for(int i=1; i<=m; i++)
        {
            scanf("%d %d", &u, &v);
            Matrix0.a[u][v] = 1;
        }

        scanf("%d", &Q);

        while(Q--)
        {
            scanf("%d %d %d", &u, &v, &k);

            Matrix answer = Pow(Matrix0, k);

            printf("%d
", answer.a[u][v]);
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5382590.html