poj 3613 矩阵快速幂变形(恰好k条边最短路)

本文介绍了一种求解特定长度的最短路径问题的方法,利用邻接矩阵和快速幂技巧实现。通过不断加倍路径长度,最终得到给定点对间确切长度k的最短路径。

题意:给定一个无向图和一个点对(a,b),求从a到b的恰好长度为k的最短路。

思路:对于图的邻接矩阵,做一次add(见代码)操作,元素变成长度为2的最短路,再自身一次就是长度为4的最短路。按照这个思路加上快速幂的思路就OK了。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <cstdlib>
using namespace std;
#define clc(s,t) memset(s,t,sizeof(s))
#define INF 0x3fffffff
#define N 205
struct edge{
    int x,y,w;
}e[105];
struct matrix{
    int a[N+5][N+5];
}g,res;
int k,m,x,y,s[N],len;
struct matrix add(matrix p,matrix q){
    struct matrix ans;
    int i,j,k;
    for(i = 1;i<=len;i++)
        for(j = 1;j<=len;j++){
            ans.a[i][j] = INF;
            for(k = 1;k<=len;k++)
                ans.a[i][j] = min(ans.a[i][j],p.a[i][k]+q.a[k][j]);
        }
    return ans;
}
void solve(int n){
    int f = 0;
    while(n){
        if(n&1){
            if(f==0){
                f = 1;
                res = g;
            }else
                res = add(res,g);
        }
        g = add(g,g);
        n>>=1;
    }
}
int main(){
    int i,j,a,b;
    scanf("%d %d %d %d",&k,&m,&x,&y);
    for(i = 0;i<m;i++){
        scanf("%d %d %d",&e[i].w,&e[i].x,&e[i].y);
        s[i*2] = e[i].x;
        s[i*2+1] = e[i].y;
    }
    sort(s,s+m*2);
    len = unique(s,s+m*2)-s;
    for(i = 1;i<=len;i++)
        for(j = 1;j<=len;j++)
            g.a[i][j] = res.a[i][j] = INF;
    for(i = 0;i<m;i++){
        a = lower_bound(s,s+len,e[i].x)-s+1;
        b = lower_bound(s,s+len,e[i].y)-s+1;
        g.a[a][b] = g.a[b][a] = e[i].w;
    }
    solve(k);
    x = lower_bound(s, s+len, x)-s+1;
    y = lower_bound(s, s+len, y)-s+1;
    printf("%d\n",res.a[x][y]);
}


以下是Java解决POJ3233—矩阵幂序列问题的代码和解释: ```java import java.util.Scanner; public class Main { static int n, k, m; static int[][] A, E; public static void main(String[] args) { Scanner sc = new Scanner(System.in); n = sc.nextInt(); k = sc.nextInt(); m = sc.nextInt(); A = new int[n][n]; E = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { A[i][j] = sc.nextInt() % m; E[i][j] = (i == j) ? 1 : 0; } } int[][] res = matrixPow(A, k); int[][] ans = matrixAdd(res, E); printMatrix(ans); } // 矩阵乘法 public static int[][] matrixMul(int[][] a, int[][] b) { int[][] c = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { for (int k = 0; k < n; k++) { c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % m; } } } return c; } // 矩阵快速幂 public static int[][] matrixPow(int[][] a, int b) { int[][] res = E; while (b > 0) { if ((b & 1) == 1) { res = matrixMul(res, a); } a = matrixMul(a, a); b >>= 1; } return res; } // 矩阵加法 public static int[][] matrixAdd(int[][] a, int[][] b) { int[][] c = new int[n][n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { c[i][j] = (a[i][j] + b[i][j]) % m; } } return c; } // 输出矩阵 public static void printMatrix(int[][] a) { for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { System.out.print(a[i][j] + " "); } System.out.println(); } } } ``` 解释: 1. 首先读入输入的n、k、m和矩阵A,同时初始化单位矩阵E。 2. 然后调用matrixPow函数求出A的k次幂矩阵res。 3. 最后将res和E相加得到结果ans,并输出。 4. matrixMul函数实现矩阵乘法,matrixPow函数实现矩阵快速幂,matrixAdd函数实现矩阵加法,printMatrix函数实现输出矩阵
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值