• 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;
    }
    
    
  • 相关阅读:
    Moebius实现Sqlserver集群~介绍篇
    知方可补不足~SQL数据库用户的克隆,SQL集群的用户同步问题
    从零开始学C++之动态创建对象
    [置顶] 某大型银行深化系统技术方案之二十五:性能设计之主要数量指标
    POJ 1300 Door Man
    解决SQL查询总是超时已过期
    hdu 1728 逃离迷宫(BFS)
    Nginx 负载均衡-加权轮询策略剖析
    ios 6 横竖屏转换
    firefox同步数据时无响应问题
  • 原文地址:https://www.cnblogs.com/luyiming123blog/p/P6190.html
Copyright © 2020-2023  润新知