HDU2807 - The Shortest Path - 最短路之矩阵乘法

本文介绍了一种基于矩阵运算的城市间路径寻路算法。通过定义特定的矩阵乘法规则,来判断两个城市间是否存在道路连接,并计算最短路径。文章提供了完整的AC代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.题目描述:

The Shortest Path

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3314    Accepted Submission(s): 1097


Problem Description
There are N cities in the country. Each city is represent by a matrix size of M*M. If city A, B and C satisfy that A*B = C, we say that there is a road from A to C with distance 1 (but that does not means there is a road from C to A).
Now the king of the country wants to ask me some problems, in the format:
Is there is a road from city X to Y?
I have to answer the questions quickly, can you help me?
 

Input
Each test case contains a single integer N, M, indicating the number of cities in the country and the size of each city. The next following N blocks each block stands for a matrix size of M*M. Then a integer K means the number of questions the king will ask, the following K lines each contains two integers X, Y(1-based).The input is terminated by a set starting with N = M = 0. All integers are in the range [0, 80].
 

Output
For each test case, you should output one line for each question the king asked, if there is a road from city X to Y? Output the shortest distance from X to Y. If not, output "Sorry".
 

Sample Input
  
3 2 1 1 2 2 1 1 1 1 2 2 4 4 1 1 3 3 2 1 1 2 2 1 1 1 1 2 2 4 3 1 1 3 0 0
 

Sample Output
  
1 Sorry
 

Source
 

Recommend
lcy
2.题意概述:

全国有N个城市。每个城市由M * M的矩阵大小表示。如果城市A,B和C满足A * B = C,我们说有一条从A到C的道路距离为1(但这并不意味着有一条从C到A的道路)。

问某点i到j是否有最短路,有则输出最度阿奴,无则输出0

3.解题思路:

直接码一发矩阵乘法再判断就行,这题注意的是a b c矩阵两两都不相同

4.AC代码:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define maxn 100100
#define N 88
#define eps 1e-6
#define pi acos(-1.0)
#define e exp(1.0)
using namespace std;
const int mod = 1e9 + 7;
typedef long long ll;
typedef unsigned long long ull;
struct node
{
	int to, val;
	node(int a, int b) { to = a; val = b; }
};
struct matrix
{
	int mat[N][N];
	int sz;
	friend matrix operator* (matrix a, matrix b)
	{
		matrix ans;
		ans.sz = a.sz;
		memset(ans.mat, 0, sizeof(ans.mat));
		for (int i = 0; i < ans.sz; i++)
			for (int j = 0; j < ans.sz; j++)
				for (int k = 0; k < ans.sz; k++)
					ans.mat[i][j] += a.mat[i][k] * b.mat[k][j];
		return ans;
	}
	friend bool operator== (matrix a, matrix b)
	{
		int flag = 1;
		for (int i = 0; i < a.sz && flag; i++)
			for (int j = 0; j < a.sz; j++)
				if (a.mat[i][j] != b.mat[i][j])
				{
					flag = 0;
					break;
				}
		return flag;
	}
} M[N];
vector<node> mp[N];
int dis[N];
bool vis[N];
void spfa(int sta, int n)
{
	memset(vis, 0, sizeof(vis));
	fill(dis, dis + n + 1, INF);
	deque<int> q;
	vis[sta] = 1;
	dis[sta] = 0;
	q.push_back(sta);
	while (!q.empty())
	{
		int u = q.front();
		q.pop_front();
		vis[u] = 0;
		int sz = mp[u].size();
		for (int i = 0; i < sz; i++)
		{
			int v = mp[u][i].to;
			int w = mp[u][i].val;
			if (dis[v] > dis[u] + w)
			{
				dis[v] = dis[u] + w;
				if (!vis[v])
				{
					vis[v] = 1;
					if (!q.empty() && dis[v] <= dis[q.front()])
						q.push_front(v);
					else
						q.push_back(v);
				}
			}
		}
	}
}
int main()
{
#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
	long _begin_time = clock();
#endif
	int n, m;
	while (~scanf("%d%d", &n, &m), n + m)
	{
		for (int i = 0; i < n; i++)
		{
			mp[i].clear();
			M[i].sz = m;
			for (int a = 0; a < m; a++)
				for (int b = 0; b < m; b++)
					scanf("%d", &M[i].mat[a][b]);
		}
		for (int i = 0; i < n; i++)
			for (int j = 0; j < n; j++)
			{
				matrix tmp = M[i] * M[j];
				for (int k = 0; k < n; k++)
					if (k != i && k != j && M[k] == tmp)
						mp[i].push_back(node(k, 1));
			}
		int k;
		scanf("%d", &k);
		while (k--)
		{
			int s, t;
			scanf("%d%d", &s, &t);
			s--;
			t--;
			spfa(s, n);
			if (dis[t] == INF)
				puts("Sorry");
			else
				printf("%d\n", dis[t]);
		}
	}
#ifndef ONLINE_JUDGE
	long _end_time = clock();
	printf("time = %ld ms.", _end_time - _begin_time);
#endif
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值