2D poj Cow Relays——folyd+矩阵快速幂

Cow Relays

题目传送门
For their physical fitness program, (N (2 ≤ N ≤ 1,000,000)) cows have decided to run a relay race using the (T (2 ≤ T ≤ 100)) cow trails throughout the pasture.

Each trail connects two different intersections ((1 ≤ I_{1i} ≤ 1,000; 1 ≤ I_{2i} ≤ 1,000)), each of which is the termination for at least two trails. The cows know the lengthi of each trail ((1 ≤ length_i ≤ 1,000)), the two intersections the trail connects, and they know that no two intersections are directly connected by two different trails. The trails form a structure known mathematically as a graph.

To run the relay, the N cows position themselves at various intersections (some intersections might have more than one cow). They must position themselves properly so that they can hand off the baton cow-by-cow and end up at the proper finishing place.

Write a program to help position the cows. Find the shortest path that connects the starting intersection (S) and the ending intersection (E) and traverses exactly N cow trails.

Input

  • Line 1: Four space-separated integers: N, T, S, and E
  • Lines 2..T+1: Line i+1 describes trail i with three space-separated integers: (length_i) , (I_{1i}) , and (I_{2i})

Output

  • Line 1: A single integer that is the shortest distance from intersection S to intersection E that traverses exactly N cow trails.

Sample Input

2 6 6 4
11 4 6
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9

Sample Output

10

Solve

看见数据范围,边的数量不大于100,那么点的数量也就不到100,既然是最短路,那就想到Folyd算法

//板子
for(int k = 1; k <= n; k++)
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            f[i][j] = min(f[i][j], f[i][k] + f[k][j])

这个很简单

然后,我们假设a数组是通过了x条边的最短路,b数组是通过了y条边的最短路

for(int k = 1; k <= tot; k++)
    for(int i = 1; i <= tot; i++)
        for(int j = 1; j <= tot; j++)
            c[i][j] = min(c[i][j], a[i][k] + b[k][j]);

通过这样,显然我们就得到了c数组是通过了(x+y)条边的最短路

要经过N条边,就是对原来的邻接矩阵进行N-1操作就行

矩阵快速幂
我们把每一次操作看成一次矩阵乘法,就可以用矩阵快速幂来优化

快速幂

int Pow(int a, int x) {
    int ans = 1;
    for (; x; x >>= 1, a = (ll)a * a % M)
        if (x & 1) ans = (ll)ans * a % M;
    return ans;
}

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n, k, s, t, m[1005], tot;
struct node {
    int a[105][105];
    node operator * (const node& b) const {
        node c;
        memset(c.a, 0x3f, sizeof(c.a));
        for(int k = 1; k <= tot; k++)
            for(int i = 1; i <= tot; i++)
                for(int j = 1; j <= tot; j++)
                    c.a[i][j] = min(c.a[i][j], a[i][k] + b.a[k][j]);
        return c;
    }//重载运算符 * 
}a;//定义矩阵结构体
node qpow(node a, int x) {
    node ans = a;
    x--;
    while (x) {
        if (x & 1) ans = ans * a;
        x >>= 1;
        a = a * a;
    }
    return ans;
}//快速幂
int main() {
    memset(a.a, 0x3f, sizeof(a.a));
    scanf("%d%d%d%d", &k, &n, &s, &t);
    for(int i = 1, x, y, z; i <= n; i++) {
        scanf("%d%d%d", &z, &x, &y);
        if (!m[x]) m[x] = ++tot;
        if (!m[y]) m[y] = ++tot;
        //这里是离散化
        a.a[m[x]][m[y]] = a.a[m[y]][m[x]] = z;
    }
    a = qpow(a, k);
    printf("%d", a.a[m[s]][m[t]]);
    //注意已经进行了离散化
    return 0;
}
原文地址:https://www.cnblogs.com/shawk/p/12793956.html