【POJ3613 Cow Relays】(廣義矩陣乘法)

題目鏈接
先離散化,假設有\(P\)個點
定義矩陣\(A_{ij}\)表示\(i\)\(j\)只經過一條邊的最短路,\[{(A^{a+b})_{ij}=\min_{1\le k\le p} \{ (A^a)_{ik}+(A^b)_{kj} \}}\]
\(A^{a+b}_{ij}\)表示\(i\)\(j\)經過\((a+b)\)條邊的最短路。
這不就是\(ddp\)裏常用的廣義矩陣乘法嗎,直接上快速冪即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int b[1010], n, m, s, t, cnt, A, B, C;
struct Matrix{
    int a[220][220];
}M;
Matrix operator * (Matrix a, Matrix b){
    Matrix c;
    for(int i = 1; i <= cnt; ++i)
        for(int j = 1; j <= cnt; ++j){
            c.a[i][j] = 1 << 29;
            for(int k = 1; k <= cnt; ++k)
                c.a[i][j] = min(c.a[i][j], a.a[i][k] + b.a[k][j]);
        }
    return c;
}
int main(){
    scanf("%d%d%d%d", &n, &m, &s, &t);
    memset(M.a, 63, sizeof M.a);
    for(int i = 1; i <= m; ++i){
        scanf("%d%d%d", &C, &A, &B);
        if(!b[A]) b[A] = ++cnt;
        if(!b[B]) b[B] = ++cnt;
        M.a[b[A]][b[B]] = M.a[b[B]][b[A]] = C;
    }
    Matrix now = M; --n;
    while(n){
        if(n & 1) now = now * M;
        M = M * M; n >>= 1;
    }
    printf("%d\n", now.a[b[s]][b[t]]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章