poj 3613 Cow Relays

题意:

已知起点 s 与终点 e,要求走 N 条边的最短路。

思路:

应用动态规划的思维。

邻接矩阵上的乘法,应用快速幂。

参考论文:*俞华程《矩阵乘法在信息学中的应用》

PS:

网上解题报告看过很多,但我觉得推导中都偏重与 floyd 算法。

论文里邻接矩阵乘法的内容,很好的解释了,为什么答案是一个矩阵连乘的结果。

纪念一下这道题。

/*
无向图,已知起点和终点,要求走严格 N 条边的最短路。
点数 <= 200
N <= 1000000
邻接矩阵上的乘法,应用快速幂。
*俞华程《矩阵乘法在信息学中的应用》
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 110;
struct M{
	int mm[maxn][maxn];
	M()
	{
		memset( mm, -1, sizeof(mm) );
	}
}mat, tmat;
int cnt, f[1000010];
int k, m, s, e;
int min( int a, int b ){ return a < b ? a : b; }
void init()
{
	memset( f, 0, sizeof(f) );
	cnt = 0;
}
M matMul( M mat, M tmat )
{
	M temp;
	int i, j, t;
	for( i = 1; i <= cnt; i++ )
	{
		for( j = 1; j <= cnt; j++ )
		{
			for( t = 1; t <= cnt; t++ )
			{
				if( tmat.mm[t][j] != -1 && mat.mm[i][t] != -1 
					&& ( temp.mm[i][j] == -1 || temp.mm[i][j] > mat.mm[i][t] + tmat.mm[t][j] ) )
					temp.mm[i][j] = mat.mm[i][t] + tmat.mm[t][j];
			}
		}
	}
	return temp;
}
int main()
{
	scanf( "%d%d%d%d", &k, &m, &s, &e );
	int i, u, v, w;
	init();
	for( i = 0; i < m; i++ )
	{
		scanf( "%d%d%d", &w, &u, &v );
		if( !f[u] )f[u] = ++cnt;
		if( !f[v] )f[v] = ++cnt;
		tmat.mm[f[u]][f[v]] = tmat.mm[f[v]][f[u]] = w;
	}
	int num = 0;
	while( k )
	{
		if( k & 1 )
		{
			if( !num )
			{
				mat = tmat;
				num = 1;
			}
			else mat = matMul( mat, tmat );
		}
		tmat = matMul( tmat, tmat );
		k >>= 1;
	}
	printf( "%d\n", mat.mm[f[s]][f[e]] );
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值