poj 3613 矩阵快速幂变形(恰好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]);
}


你可能感兴趣的:(poj 3613 矩阵快速幂变形(恰好k条边最短路))