小白月赛13 小A的路径 (矩阵快速幂求距离为k的路径数)

链接:https://ac.nowcoder.com/acm/contest/549/E
来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

小A来到了一个陌生的城镇,这个城镇与其它城镇之间构成了集群。城镇之间的路径都是单向的,而小A每一天都能由一个城镇走到另外一个城镇。小A将会连续走k天,直到抵达某个城镇。也许他并不能走到这个城镇,那么可以认为不存在这样的路径,也就是路径数为0。否则就会有若干条路径可以抵达某个城镇。现在他想知道,如果他从给定某个城市出发,k天之后到达其它城镇的路径的总和是多少。数据不保证没有重边,也就是说可能每一天从一个城镇到另外一个城镇之间会有多条路径。路径总和可能会非常大,对答案模上1000000007。

输入描述:

NMKSNMKAKSAMuvuv第一行三个整数N,M,K,S分别表示一共有N个城镇,城镇之间有M条单向边。K表示小A连续走K天。S表示小A出发的那个城镇。接下来的M行每行两个整数u,v表示从城镇u连了一条有向边到城镇v。

输出描述:

A一行输出一个结果,表示小A到其余城镇路径数的总和。
示例1

输入

复制
4 5 2 1
1 2
1 3
2 3
4 1
3 4

输出

复制
2

说明

经过2天,小A可以走到3号城镇或者4号城镇,到3号城镇的路径有一条是1-2-3,到4号城镇的路径也是一条是1-3-4,共计有两条路径。

备注:

1N100, 1K1e91≤N≤100, 1≤K≤1e9
 
解题思路:建立一个矩阵,用以表示任意两个顶点之间是否有边,如果有矩阵上就为1,反之为0。
那么此时如果 这个矩阵乘这个矩阵,意思就成了这个矩阵u到w长度为1的个数乘上w到v长度为1的个数,也就成了长度为2的个数的多少(边取得任意多次)。
此时得到的k=2的矩阵,这个矩阵乘长度为1的矩阵还是这个矩阵u到w长度为2的个数乘上w到v长度为1的个数,也就是长度为3的矩阵个数
这么乘可以用快速幂求出
代码;
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
int n,m,k,s;
struct Matrix{
    ll a[105][105];
    Matrix(){
        memset(a,0,sizeof(a));
    }
    Matrix operator *(const Matrix & x)const{
        Matrix ans;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                for(int k=1;k<=n;k++)
                    ans.a[i][j]=(ans.a[i][j]+a[i][k]*x.a[k][j])%mod;
        return ans;
    }
};
Matrix mp,res;
void qpow(int y){
    for(int i=1;i<=n;i++)res.a[i][i]=1;
    while(y){
        if(y&1) res=res*mp;
        mp=mp*mp;
        y>>=1;
    }
}
int main(){
    cin>>n>>m>>k>>s;
    for(int i=1;i<=m;i++){
        int u,v;
        cin>>u>>v;
        mp.a[u][v]++;
    }
    qpow(k);
    ll ans=0;
    for(int i=1;i<=n;i++){
        if(i!=s) ans=(ans+res.a[s][i])%mod;
    }
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/zjl192628928/p/10770557.html