武大校赛E题

E. Lost in WHU

题意是给定一副无向图,然后求走了T步之内,从起点到终点有多少走法,(有个地方题面没有说清楚,就是走到点n之后不能再往别的点走了)

邻接矩阵,乘T次之后,MAP[i][j]就是从i点走到j点的且走T步时的走法。
我们把矩阵中n到其他点的路径去掉,
所以我们要算的就是∑ (Map[1][n] )^i (1 <= i <= T)就是答案了 。于是我们要构造一个矩阵把前缀和记录一下。
由于在原来的邻接矩阵中,我们只关心的只有Map[1][n]这个值,我们可以把原矩阵放入一个新的矩阵中,或者说把矩阵拓展一维,令Map[0][n] = 1,然后把这样,Map[1][0]记录的就是上一个状态的Map[1][n],由于是要求前缀和,我们要把他再加起来,所以Map[0][0]处再添加一个1进去,这样就可以把上个状态一起加进去,递推之后Map[1][0]就是不包括当前状态前缀和,最后答案就是Map[1][n] + Map[1][0] ;

#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<set>
#include<map>
#include<time.h>
#include<cstdio>
#include<vector>
#include<stack>
#include<queue>
#include<iostream>
using namespace std;
#define  LONG long long
const int   INF=0x3f3f3f3f;
const LONG    MOD=1e9+7;
const double PI=acos(-1.0);
#define clr0(x) memset(x,0,sizeof x)
#define clrI(x) memset(x,-1,sizeof(x))
#define clr1(x) memset(x,INF,sizeof x)
#define clr2(x) memset(x,-INF,sizeof x)
#define EPS 1e-10
int n ;
struct Matr{
    LONG matr[120][120];
    Matr(LONG  x = 0)
    {
        for(int i = 0; i <= 110 ;++i)
            for(int j =0; j <= 110 ;++ j)matr[i][j] = x;
    }
    Matr ( LONG x,int y)
    {
        clr0(matr);
        for(int i = 0 ; i <= y ; ++ i)matr[i][i] = x ;
    }
};
Matr operator * (Matr &a , Matr &b)
{
    Matr ans (0);
    for(int i = 0 ; i<= n ; ++ i)
    {
        for(int j =0; j<= n ; ++ j)
            for(int k = 0; k <= n ;++ k)
        ans.matr[i][j] = (ans.matr[i][j] +  a.matr[i][k] * b.matr[k][j] ) % MOD;
    }
    return ans ;
}
Matr Equ(Matr &a , Matr &b)
{

    for(int i =0; i<=n ;++ i)
        for(int j =0; j<= n ;++ j)a.matr[i][j] = b.matr[i][j];
    return a;
}
Matr Q_pow_M( Matr &a , LONG b)
{
    Matr res(1 , n);
    while(b)
    {
        if(b & 1)
            res = res * a ;
        a = a * a;
        b /= 2;
    }
    return res ;
}

int main()
{
//freopen("C:\\Users\\ZhangYuyang\\Desktop\\in.txt","r",stdin);
//freopen("C:\\Users\\ZhangYuyang\\Desktop\\out1.txt","w",stdout);
    int m;
    while(~scanf("%d%d",&n,&m))
    {
    Matr take(0) ;
    take.matr[0][0] = 1 , take.matr[n][0] = 1 ;
    for(int i =1; i<= m ;++ i)
    {
        int a, b;
        scanf("%d%d",&a,&b);
        if(a != n)
        take.matr[a][b] = 1;
        if(b != n )
        take.matr[b][a] = 1;
    }
    int T ;
    cin>> T ;
    Matr tmp(0);
    Matr ans(0);
    ans = Q_pow_M( take , T  ) ;
    cout<<( ans.matr[1][n] + ans.matr[1][0] ) % MOD<<endl ;
    LONG sum = 0;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值