• 【模板】倍增+Floyd


    题目大意:给定一个 N 个顶点的邻接矩阵、起点顶点、终点顶点,求至少经过 K 条边(边可以重复)从起点到终点的最短路长度,若不能到达,输出 -1。

    题解:至少经过 K 条边和恰好经过 K 条边的初始条件不同,因为至少经过 1 条边的任意两点最短路就是通过 Floyd 算法算出的矩阵,而恰好经过 K 条边的任意两点的最短路则是最初的邻接矩阵。不过两个算法的矩阵幂算法是相同的,可以用快速幂加速递推。

    代码如下

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=101;
    const int inf=0x3f3f3f3f;
    
    int n,k,st,ed;
    struct matrix{
    	int data[maxn][maxn];
    	matrix(){memset(data,0x3f,sizeof(data));}
    	inline int* operator[](int i){return data[i];}
    	friend matrix operator*(matrix& x,matrix& y){
    		matrix z;
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    				for(int k=1;k<=n;k++)
    					z[i][j]=min(z[i][j],x[i][k]+y[k][j]);
    		return z;
    	}
    }d,ans;
    
    void read_and_parse(){
    	scanf("%d%d%d%d",&n,&k,&st,&ed);
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++){
    			scanf("%d",&d[i][j]);
    			if(d[i][j]==-1)d[i][j]=inf;
    		}
    }
    
    void floyd(){
    	for(int k=1;k<=n;k++)
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    				d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    }
    
    void solve(){
    	floyd();
    	ans=d,k--; 
    	for(;k;k>>=1,d=d*d)if(k&1)ans=ans*d;
    	if(ans[st][ed]==inf)puts("-1");
    	else printf("%d
    ",ans[st][ed]);
    } 
    
    int main(){
    	read_and_parse();
    	solve();
    	return 0;
    }
    
  • 相关阅读:
    node爬取html乱码
    mysql字段有中英文,数字按照升序/降序 排序
    解决git反复输入密码的问题
    vue在jsx中使用for循环
    vscode插件篇
    table无法控制宽度
    console输出彩色字体
    原生js实现vue组件功能
    ES6中的proxy
    面向对象编程
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/9986334.html
Copyright © 2020-2023  润新知