Educational DP Contest R - Walk(倍增floyd)

R - Walk

原题链接:https://atcoder.jp/contests/dp/tasks/dp_r

题目大意:

给一个有向图,求经过k条边的路径个数(允许重复)。

解题思路:

倍增folyd算法,求解一个图中经过k条边的路径最大距离或最小距离或经过k条边的路径有多少个时要用到,也叫做矩阵乘法。首先,我们有两个矩阵,如果其中一个矩阵代表恰好经过x条边的最短路,另外一个矩阵代表恰好经过y条边的最短路。那么将这两个矩阵合并就代表恰好经过x+y条边的最短路。

本题给出的二维矩阵就是经过一条边的所有路径个数,然后利用快速幂与矩阵相乘求出经过k条边的路径。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 #define debug(a) cout<<#a<<":"<<a<<endl;
 5 const ll INF=0x3f3f3f3f;
 6 const ll N=1e6+7;
 7 const ll mod=1e9+7;
 8 ll maxn,minn;
 9 ll T,n,m,k;
10 
11 ll f;
12 struct node{
13     ll arr[100][100];
14 };
15 
16 node mul(node x,node y){
17     node ans;
18     memset(ans.arr,0,sizeof(ans.arr));
19      for(ll k = 1;k<=n;k++){
20         for(ll i = 1;i<=n;i++){
21             for(ll j = 1;j<=n;j++){
22                 ans.arr[i][j] = (ans.arr[i][j]+(x.arr[i][k]*y.arr[k][j])%mod)%mod;
23             }
24         }
25     }
26     return ans;
27 }
28 node ksm(node a,ll b){
29     node ans;
30     memset(ans.arr,0,sizeof(ans.arr));
31     for(ll i=1;i<=f;i++)
32         ans.arr[i][i]=1;
33     while(b){
34         if(b&1) ans=mul(ans,a);
35         a=mul(a,a);    b>>=1;
36     }
37     return ans;
38 }
39 
40 
41 int main(){
42     ll ans=0;
43     node x,y;
44     cin>>n>>k;
45     f=n;
46     for(ll i=1;i<=n;i++){
47         for(ll j=1;j<=n;j++){
48             scanf("%lld",&x.arr[i][j]);
49         }
50     }
51     y=ksm(x,k);
52     for(ll i=1;i<=n;i++){
53         for(ll j=1;j<=n;j++){
54             ans=(ans+y.arr[i][j])%mod;
55         }
56     }
57     cout<<ans<<endl;
58     return 0;
59 }

 

 
posted @ 2020-05-08 19:58  yya雨  阅读(346)  评论(1编辑  收藏  举报