Description

HH 有个一成不变的习惯, 喜欢饭后百步走. 所谓百步走, 就是散步, 就是在一定的时间内, 走过一定的距离. 但是同时 HH 又是个喜欢变化的人, 所以他不会立刻沿着刚刚走来的路走回. 又因为 HH 是个喜欢变化的人, 所以他每天走过的路径都不完全一样, 他想知道他究竟有多少 种散步的方法. 现在给你学校的地图 (假设每条路的长度都是一样的都是 \(1\)) , 问长度为 \(t\), 从给定地点 \(A\) 走到给定地点 \(B\) 共有多少条符合条件的路径.

Input

第一行: 五个整数 \(n, m, t, A, B\). 其中 \(n\) 表示学校里的路口的个数,\(m\) 表示学校 里的路的条数,\(t\) 表示 HH 想要散步的距离,\(A\) 表示散步的出发点, 而 \(B\) 则表示散步的 终点.

接下来 \(m\) 行, 每行一组 \(A_i, B_i\), 表示从路口 \(A_i\) 到路口 \(B_i\) 有一条路. 数据 保证 \(A_i \neq B_i\), 但不保证任意两个路口之间至多只有一条路相连接. 路口编号从 \(0\)\(n - 1\). 同一行内所有数据均由一个空格隔开, 行首行尾没有多余空格. 没有多余 空行. 答案模 \(45989\).

Output

一行, 表示答案.

Sample Input

4 5 3 0 0
0 1
0 2
0 3
2 1
3 2

Sample Output

4

Data Range

对于 30% 的数据,\(n \leq 4, m \leq 10, t \leq 10\).

对于 100% 的数据,\(n \leq 20, m \leq 60, t \leq 2^30, 0 \leq A, B \lt n\).

Explanation

一个比较神的邻接矩阵乘法, 没怎么看懂~

Source Code


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>

using namespace std;
typedef long long lli;
const int maxn = 130;
const int modr = 45989;

struct edge
{
    int u, v;
    edge *next, *rev;
};
int ecnt;
edge *edges[maxn], epool[maxn];
void add_edge(int u, int v)
{
    edge *p = &epool[++ecnt],
         *q = &epool[++ecnt];
    p->u = u; p->v = v; p->next = edges[u]; edges[u] = p;
    q->u = v; q->v = u; q->next = edges[v]; edges[v] = q;
    p->rev = q; q->rev = p;
    return ;
}

struct matrix {
    lli val[maxn][maxn];
    matrix(void) {
        memset(val, 0, sizeof(val));
        return ; }
    matrix(int a) {
        memset(val, 0, sizeof(val));
        for (int i = 1; i <= ecnt; i++)
            val[i][i] = a;
        return ; }
    matrix& operator *= (matrix b) {
        static lli nv[maxn][maxn];
        memset(nv, 0, sizeof(nv));
        for (int i = 1; i <= ecnt; i++)
            for (int j = 1; j <= ecnt; j++) {
                nv[i][j] = 0;
                for (int k = 1; k <= ecnt; k++)
                    nv[i][j] += val[i][k] * b.val[k][j];
                nv[i][j] %= modr;
            }
        for (int i = 1; i <= ecnt; i++)
            for (int j = 1; j <= ecnt; j++)
                val[i][j] = nv[i][j];
        return *this;
    }
};
matrix operator ^ (matrix a, int b) {
    matrix res(1);
    for (int i = b; i > 0; i >>= 1, a *= a)
        if (i & 1)
            res *= a;
    return res;
}

int n, m, dist, A, B;

int main(int argc, char** argv)
{
    scanf("%d%d%d%d%d", &n, &m, &dist, &A, &B);
    ecnt = 1;
    for (int i = 1, a, b; i <= m; i++) {
        scanf("%d%d", &a, &b);
        add_edge(a, b);
    }
    matrix matA, matB;
    for (edge *ep = edges[A]; ep; ep = ep->next) {
        matA.val[1][ep - &epool[0]] += 1;
    }
    for (int i = 2; i <= ecnt; i++)
        for (int j = 2; j <= ecnt; j++)
            if (epool[i].v == epool[j].u && epool[i].rev != &epool[j])
                matB.val[i][j] += 1;
    matA *= matB ^ (dist-1);
    lli res = 0;
    for (edge *ep = edges[B]; ep; ep = ep->next)
        res += matA.val[1][ep->rev - &epool[0]];
    res %= modr;
    printf("%lld\n", res);
    return 0;
}