POJ 3613 Cow Relays [矩阵连乘]

题意:求无向图s到t恰好经k条边(边可以重复)的最短路径

思路:(不是很清楚)类似于快速幂的矩阵相乘的方法,只是把相乘部分改成floyd。设ans[i][j]表示的i到j通过k条边的最短路径。

ans[i][j] =min (ans[i][k] + graph[k][j])

由快速幂可知:a^t = (t%2)?(a^t/2)^2 * a :  (a^t/2)^2

在处理结点编号时,最好把他们连续化,以节约空间。

#include <iostream>
#include <string.h>
using namespace std;
#define MAXN 205
#define INF 1000000000
int n,N;   //N表示连续化后的顶点数
int node[1010];   //用于连续化结点编号
int map[MAXN][MAXN], dis[MAXN][MAXN],temp[MAXN][MAXN];   //dis[i][j]存储点i到点j经 k条边 的最短路径
void floyd(int a[][MAXN],int b[][MAXN]){
    for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
            temp[i][j]=INF;
    for(int k=0;k<N;k++)
        for(int i=0;i<N;i++)
            for(int j=0;j<N;j++)
                temp[i][j]=min(a[i][k]+b[k][j],temp[i][j]);
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            a[i][j]=temp[i][j];
        }
    }
}
void counts(){
    while(n){
        if(n%2){
            floyd(dis,map);
        }
        floyd(map,map);
        n/=2;
    }
}
int main(){
    int t,s,e;
    cin>>n>>t>>s>>e;
    N=0;
    memset(node,-1,sizeof(node));
    for(int i=0;i<MAXN;i++){
        for(int j=0;j<MAXN;j++){
                dis[i][j]=INF;
                map[i][j]=INF;
                dis[i][i]=0;
        }
    }
    while(t--){
        int l,a,b;
        cin>>l>>a>>b;
        if(node[a]==-1) node[a]=N++;
        if(node[b]==-1) node[b]=N++;
        map[node[a]][node[b]]=l;
        map[node[b]][node[a]]=l;
    }
    counts();
    cout<<dis[node[s]][node[e]]<<endl;
    return 0;
}
/*测试:
Sample Input
2 6 6 4
11 4 6
4 4 8
8 4 9
6 6 8
2 6 9
3 8 9
Sample Output
10
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值