P6190 魔法

给一个(n)(m)边的有向图,可以使用(k)次魔法,每次魔法将边权变为相反数,求从(1)(n)的最短路。
(n le 100,m le 2500,k le 10^6)

  • (k = 0)
    ( exttt{Floyd})即可,设(f_{i,j})为从(i)(j)的最短路,初始化为(inf)(有边权或(i=j)除外),转移:

[f_{i,j} = min {f_{i,k} + f_{k,j}} ]

  • (k = 1)
    枚举使用魔法的边权。

[f_{1,i,j} = min {f_{0,i,u} + f_{0,v,j} - w mid (u,v,w) in mathbf{E}} ]

  • (k > 1)

[f_{a + b,i,j} = min {f_{a,i,k} + f_{b,k,j}} ]

矩阵优化,(mathcal{O}(n ^ 3 log {k} + n ^ 2 m + n ^ 3))

#include <bits/stdc++.h>
#include <time.h>
using namespace std;
#define int long long

const int N = 102, inf = 1e12;

int n, m, k;

struct Matrix
{
    long long a[N][N];
    void clear(long long x)
    {
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                a[i][j] = x;
            }
        }
        return;
    }
} F, A;

struct edge
{
    int from, to;
    long long w;
};

edge E[2505];
int top = 0;

Matrix operator*(const struct Matrix &x, const struct Matrix &y)
{
    Matrix ans;
    ans.clear(inf);
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            for (int k = 1; k <= n; k++)
            {
                ans.a[i][j] = min(ans.a[i][j], x.a[i][k] + y.a[k][j]);
            }
        }
    }
    return ans;
}

void Floyd(void)
{

    for (int k = 1; k <= n; k++)
    {
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                F.a[i][j] = min(F.a[i][j], F.a[i][k] + F.a[k][j]);
            }
        }
    }
    return;
}

void Get_A(void)
{
    A.clear(inf);
    for (int k = 1; k <= m; k++)
    {
        int u = E[k].from, v = E[k].to;
        long long w = E[k].w;
        // printf("u = %d,v = %d,w = %lld
", u, v, w);
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                A.a[i][j] = min(A.a[i][j], min(F.a[i][j], F.a[i][u] + F.a[v][j] - w));
                // printf("i = %d,j = %d,k = %d
", i, j, k);
            }
        }
    }
    return;
}

Matrix qmul(struct Matrix x, int p)
{
    Matrix ans;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            ans.a[i][j] = F.a[i][j];
        }
    }
    while (p)
    {
        if (p & 1)
        {
            ans = ans * x;
        }
        x = x * x;
        p >>= 1;
    }
    return ans;
}

signed main(void)
{
    // freopen("P6190.in", "r", stdin);
    // freopen("P6190.out", "w", stdout);
    scanf("%lld%lld%lld", &n, &m, &k);
    F.clear(inf);
    for (int i = 1; i <= n; i++)
        F.a[i][i] = 0;
    for (int i = 1; i <= m; i++)
    {
        int u, v;
        long long w;
        scanf("%lld%lld%lld", &u, &v, &w);
        F.a[u][v] = w;
        E[++top] = (edge){u, v, w};
    }
    Floyd();
    // printf("Floyd : OK
");
    Get_A();
    // printf("A : OK
");
    if (k == 0)
    {
        printf("%lld
", F.a[1][n]);
        return 0;
    }
    Matrix ans = qmul(A, k);
    // ans = ans * F;
    printf("%lld
", ans.a[1][n]);
    return 0;
}

原文地址:https://www.cnblogs.com/luyiming123blog/p/P6190.html