首页 > 其他分享 >矩阵快速幂加速最短路

矩阵快速幂加速最短路

时间:2024-11-04 19:42:09浏览次数:1  
标签:10 min 样例 短路 矩阵 leq sim 加速 dp

矩阵快速幂加速最短路

通常用来优化Floyd的实现

[NOI Online #1 入门组] 魔法

题目描述

C 国由 $n$ 座城市与 $m$ 条有向道路组成,城市与道路都从 $1$ 开始编号,经过 $i$ 号道路需要 $t_i$ 的费用。

现在你要从 $1$ 号城市出发去 $n$ 号城市,你可以施展最多 $k$ 次魔法,使得通过下一条道路时,需要的费用变为原来的相反数,即费用从 $t_i$ 变为 $-t_i$。请你算一算,你至少要花费多少费用才能完成这次旅程。

注意:使用魔法只是改变一次的花费,而不改变一条道路自身的 $t_i$;最终的费用可以为负,并且一个城市可以经过多次(包括 $n$ 号城市)。

输入格式

输入的第一行有三个整数,分别代表城市数 $n$,道路数 $m$ 和魔法次数限制 $k$。

第 $2$ 到第 $(m + 1)$ 行,每行三个整数。第 $(i + 1)$ 行的整数 $u_i, v_i, t_i$ 表示存在一条从 $u_i$ 到 $v_i$ 的单向道路,经过它需要花费 $t_i$。

输出格式

输出一行一个整数表示最小的花费。

样例 #1

样例输入 #1

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

样例输出 #1

-8

样例 #2

样例输入 #2

2 2 2
1 2 10
2 1 1

样例输出 #2

-19

提示

输入输出样例 1 解释

依次经过 $1$ 号道路、$2$ 号道路、$3$ 号道路,并在经过 $1,2$ 号道路前使用魔法。

输入输出样例 2 解释

依次经过 $1$ 号道路、$2$ 号道路、$1$ 号道路,并在两次经过 $1$ 号道路前都使用魔法。

数据规模与约定

本题共 $20$ 个测试点,各测试点信息见下表。

测试点编号 $n \leq$ $m \leq$ $k \leq$ 无环
$1 \sim 2$ $5$ $20$ $0$ 不保证
$3 \sim 4$ $10$ $20$ $50$ 不保证
$5 \sim 6$ $10$ $20$ $0$ 不保证
$7 \sim 8$ $20$ $200$ $50$
$9 \sim 10$ $20$ $200$ $0$ 不保证
$11 \sim 12$ $100$ $200$ $50$
$13 \sim 14$ $100$ $200$ $50$ 不保证
$15 \sim 18$ $100$ $2500$ $1000$ 不保证
$19 \sim 20$ $100$ $2500$ $10^6$ 不保证

对于【无环】一栏为“是”的测试点,保证给出的图是一张有向无环图,否则不对图的形态做任何保证。

对于全部的测试点,保证:

  • $1 \leq n \leq 100$,$1 \leq m \leq 2500$,$0 \leq k \leq 10^6$。
  • $1 \leq u_i, v_i \leq n$,$1 \leq t_i \leq 10^9$。
  • 给出的图无重边和自环,且至少存在一条能从 $1$ 到达 $n$ 的路径。

首先有70分的做法,即使用动态规划。

将边存入数组中,$g[i].u$和$g[i].v$表示边的两端,g[i].w表示边权

设$dp[i][j][k]$表示从i到j使用k次魔法时的最短路。

当k=0时:$dp[i][j][0]=min(dp[i][j][0],dp[i][k][0]+dp[k][j][0])$

当k=1时:$dp[i][j][1]=min(dp[i][j][1],dp[i][g[k].u][0]+dp[g[k].v][j][0]-g[k].w)$

使用k次魔法:$dp[i][j][k]=min(dp[i][j][k],dp[i][l][k-1]+dp[l][j][1])$

$k-1+1$刚好为k,表示魔法的使用次数。

最后输出$dp[1][n][k]$即为答案。

但是这个做法的时间复杂度为$O(n3k)$,空间复杂度为$O(n2k)$,无法AC。

这里就需要用一个工具——矩阵加速来降低复杂度了。

先对处理样例1时dp数组进行打表:

k=0时:

0 5 9 10
\ 0 4 5 
\ \ 0 1
\ \ \ 0

k=1时:

\ -5 -1  0
\  0 -4 -3
\  \  0 -1
\  \  \  0

k=2时:

0 -5 -9 -8
\  0 -4 -5
\  \  0 -1
\  \  \  0

按照题目要求,可以把矩阵乘法进行修改:

$\begin{bmatrix}a_{1,1}&a_{1,2}&a_{1,3}&a_{1,4}\a_{2,1}&a_{2,2}&a_{2,3}&a_{2,4}\a_{3,1}&a_{3,2}&a_{3,3}&a_{3,4}\a_{4,1}&a_{4,2}&a_{4,3}&a_{4,4}\\end{bmatrix} *\begin{bmatrix}b_{1,1}&b_{1,2}&b_{1,3}&b_{1,4}\b_{2,1}&b_{2,2}&b_{2,3}&b_{2,4}\b_{3,1}&b_{3,2}&b_{3,3}&b_{3,4}\b_{4,1}&b_{4,2}&b_{4,3}&b_{4,4}\\end{bmatrix}=\begin{bmatrix}min(a_{1,k},b_{k,1})&min(a_{1,k},b_{k,2})&min(a_{1,k},b_{k,3})&min(a_{1,k},b_{k,4})\min(a_{2,k},b_{k,1})&min(a_{2,k},b_{k,2})&min(a_{2,k},b_{k,3})&min(a_{2,k},b_{k,4})\min(a_{3,k},b_{k,1})&min(a_{3,k},b_{k,2})&min(a_{3,k},b_{k,3})&min(a_{3,k},b_{k,4})\min(a_{4,k},b_{k,1})&min(a_{4,k},b_{k,2})&min(a_{4,k},b_{k,3})&min(a_{4,k},b_{k,4})\\end{bmatrix}$

验证后可得到

另初始矩阵为$E_{1}$,第二个矩阵为$E_{2}$,可得到$E_{k}=E_{1}*E_{2}^k$

$E_{1}$$E_{2}$可用动态规划(Floyd) 直接求得,然后在用ksm即可快速得到答案。

时间复杂度为$O(n2m+n3log(k))$,空间复杂度为$O(n^2)$,完全可通过此题。

#include<bits/stdc++.h>
#define inf 1000000000000000
using namespace std;
const int N=110;
struct Matrix{		//矩阵
    long long a[N][N];
    int n,m;
    Matrix(int n=0,int m=0):n(n),m(m){}
    void init(){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(i==j) a[i][j]=0;
                else a[i][j]=inf;
            }
        }
    }
    Matrix operator*(const Matrix&A) const{
        Matrix ret(n,A.n);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=A.m;j++){
                long long tmp=inf;
                for(int k=1;k<=m;k++) tmp=min(tmp,a[i][k]+A.a[k][j]);
                ret.a[i][j]=tmp;
            }
        }
        return ret;
    }
};
Matrix ksm(Matrix A,int b){		//快速幂
    Matrix ret(A.n,A.n);
    ret.init();
    while(b){
        if(b&1) ret=ret*A;
        b>>=1;
        A=A*A;
    }
    return ret;
}
int main(){
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    Matrix D(n,n),K(n,n);
    D.init();
    K.init();
    for(int i=1;i<=m;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        D.a[u][v]=w;
        K.a[u][v]=-w;
    }
    Matrix G=ksm(D,n-1);
    G=G*ksm(K*G,k);
    printf("%lld",G.a[1][n]);
    return 0;
}

标签:10,min,样例,短路,矩阵,leq,sim,加速,dp
From: https://www.cnblogs.com/imfbustxhf/p/18526083

相关文章

  • 寻找两条最短路的公共路径
    寻找两条最短路的公共路径[SDOI2009]Elaxia的路线题目描述最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们必须合理地安排两个人在一起的时间。Elaxia和w**每天都要奔波于宿舍和实验室之间,他们希望在节约时间的前提下,一起走的时间尽可能的......
  • 迷宫问题(最短路径)——分别用DFS、BFS解决
    目录问题描述利用DFS(深度优先搜索)求解利用BFS(广度优先搜索)求解问题描述定义一个二维数组N*M,如5 × 5数组下所示:int maze[5][5] = {0, 1, 0, 0, 0,0, 1, 1, 1, 0,0, 0, 0, 0, 0,0, 1, 1, 1, 0,0, 0, 0, 1, 0,};它表示一个迷宫,其中的......
  • 深入解析Amdahl定律与Gustafson定律:并行计算的加速之道
    如果你觉得这篇文章对你有帮助,请不要吝惜你的“关注”、“点赞”、“评价”、“收藏”,你的支持永远是我前进的动力~~~个人收藏的技术大会分享PDF文档,欢迎点击下载查看!!!本文将探讨并行计算中的两个重要定律——Amdahl定律和Gustafson定律。通过分析这两个定律的原理、区别及实......
  • 【模板】矩阵运算
    不进行没必要的解释,主要记录模板。structMatrix{intn,m,rec[N][N]; //矩阵的长,宽和二维数组Matrix(int_n,int_m){n=_n,m=_m,memset(rec,0,sizeofrec);} //初始化函数voidreset(){n=0,m=0,memset(rec,0,sizeofrec);}......
  • luoguP1005 矩阵取数游戏
    有n*m的矩阵,每个元素a[i][j]均为非负整数,游戏规则如下:每轮从每行各取一个元素,共n个。经过m轮后取完所有元素。每次取走的元素只能是该元素所在行的行首或行尾。每轮取数都有一个分值,为每行取数的得分之和,每行取数的得分为被取走的元素值乘以2的i次方,其中i为取数轮次,从1开始。......
  • 【笔记/模板】Johnson全源最短路
    模板题目www.luogu.com.cn//Problem:P5905【模板】全源最短路(Johnson)//Contest:Luogu//URL:https://www.luogu.com.cn/problem/P5905//MemoryLimit:128MB//TimeLimit:1000ms////PoweredbyCPEditor(https://cpeditor.org)#include<bits/stdc++.h>......
  • 【Clikhouse 探秘】ClickHouse 物化视图:加速大数据分析的新利器
    ......
  • AI驱动的低代码未来:加速应用开发的智能解决方案
    引言随着数字化转型的浪潮席卷全球,企业对快速构建应用程序的需求愈发强烈。然而,传统的软件开发周期冗长、成本高昂,往往无法满足快速变化的市场需求。在此背景下,低代码平台逐渐成为开发者和企业的优选方案,以其“低门槛、高效率”的特性,让非技术人员也能够参与到应用开发中。然......
  • 特殊矩阵的压缩存储
    一维数组的存储结构ElemTypearr[10];各数组元素大小相同,且物理上连续存放。 数组元素a[i]的存放地址=LOC+i*sizeof(ElemType)。(LOC为起始地址)二维数组的存储结构ElemTypeb[2][4];二维数组也具有随机存取的特性(需要明确是行优先还是列优先)。 普通矩阵的存......
  • 免费领取7天会员加速器口令
    现在,新用户有机会免费领取迅雷加速器的VIP会员,享受长达7+30天的加速服务。以下是详细的领取攻略:领取7天免费会员领取7天免费会员的步骤非常简单:1.下载迅雷加速器:首先,访问迅雷加速器的官方网站或应用商店,下载并安装迅雷加速器客户端。2.注册/登录账户:打开客户端后,注册新的......