2017 Wuhan University Programming Contest (Online Round) E Lost in WHU(矩阵快速幂




2017 Wuhan University Programming Contest (Online Round)



Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 512 mebibytes
As one of the most beautiful campus in China, Wuhan University is around several hills, so the road is complex and visitors always lose themselves. Give a undirected graph of WHU of NN points and a deadline, then you should count the number of plan to reach the destination by deadline (the starting point is 1 and the ending point is NN).

Input
First line contains the number of points NN (Nle 100N≤100) and the number of edges MM (Mle N(N-1)/2M≤N(N−1)/2).

The ii-th line of next MM lines contains two numbers u_iu
​i
​​ and v_iv
​i
​​ , which respents an edge (u_i, v_i)(u
​i
​​ ,v
​i
​​ ).

The last line contains the deadline TT(Tle 10^9T≤10
​9
​​ ).

Output
The number of plan to reach the destination by deadline module 10^9+710
​9
​​ +7.

Examples
Input 1
4 5
1 3
2 3
3 4
1 2
1 4
8
Output 1
170
注意:数组开LL, mod = 1e9+7;
题意:给你n个点,m条路,以及时间t,求在时间t内到达n点的方法总数;
有两点需要理解。
一:到达终点后不能继续走了,所以mt[n][i]=0;
二:只有把mt[n][n]=1,求出来的才是在时间k内能走到终点的所有方法。
举个例子
比如说有这样一组数据
1 4
1 2
2 3
2 4
3 4
3

然后构造初始矩阵A
0 1 0 1
1 0 1 1
0 1 0 1
0 0 0 1
上面的mat[1][n]代表1到n需要走1单位时间的路径有几条

然后是矩阵A^2
1 0 1 2
0 2 0 3
1 0 1 2
0 0 0 1
这里第一行代表点1到点j需要走2单位时间的路径有几条

最后一列代表点i到点n需要走<=2单位时间的路径有几条(这里就是令mat[n][n]=1的妙处了)

矩阵A^3
0 2 0 4
2 0 2 5
0 2 0 4
0 0 0 1
在矩阵A^3中mat[1][n]=4,所以答案就是4了(具体详见代码)
ps:想一下矩阵是怎么乘的,就应该理解·了,我是这样理解的.(a[1][n]乘以a[n][n],才能加上小于k时间的方法,如果a[n][n]=0就加不上了,我是这样理解的)

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long int 
const int mod=1000000000+7;
int n,m;
struct mat
{
    LL mt[105][105];
    mat()
    {
        memset(mt,0,sizeof(mt));
    }
};
mat I;
mat cheng(mat q,mat p)
{
    mat c;
    mem(c.mt,0);
    for(int i=0; i<n; i++)
        for(int j=0; j<n; j++)
            for(int k=0; k<n; k++)
            {
                c.mt[i][j]=(c.mt[i][j]+q.mt[i][k]*p.mt[k][j])%mod;
            }
    return c;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {

        mat ans;
        mem(ans.mt,0);
        for(int i=0; i<m; i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(x!=n) ans.mt[x-1][y-1]=1;//到达n后不能再走
            if(y!=n) ans.mt[y-1][x-1]=1;//到达n后不能再走
        }
        ans.mt[n-1][n-1]=1;//计算<=k步的路径总数,如果为0,则计算=k时的路径数  
        int k;
        scanf("%d",&k);
        I=ans;
        mem(ans.mt,0);
        for(int i=0; i<n; i++)
            ans.mt[i][i]=1;
        while(k)
        {
            if(k&1) ans=cheng(ans,I);
            I=cheng(I,I);
            k>>=1;
        }
        printf("%lld
",ans.mt[0][n-1]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zxy160/p/7215118.html