HDU 2807 The Shortest Path 把矩阵抽象成点+Floyd

题意:有n个m*m的矩阵,设矩阵A,B,C,如果A*B=C表示从A到B有一条权值为1的边。有q次询问,如果第i个矩阵到第j个矩阵有路径,则输出最短,无则输出sorry。


想法:比较简单,矩阵抽象为点,寻求,矩阵之间的单向关系,然后建边,题目询问可能很大,显然Floyd。spfa为单源最短路,需要枚举,所以耗时。


#include<iostream>
#include<cstring>
#include<cstdio>
#define inf 111111111
using namespace std;
const int NE=85;
int n,m;
int g[NE][NE][NE],map[NE][NE],mul_g[NE][NE];
void mul(int a[NE][NE],int b[NE][NE])
{
	for(int i=1;i<=m;i++)
	for(int j=1;j<=m;j++)
	mul_g[i][j]=0;
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		{
			for(int k=1;k<=m;k++)
			{
				mul_g[i][j]+=a[i][k]*b[k][j];
			}
		}
	}
}
bool judge(int x)
{
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(mul_g[i][j]!=g[x][i][j])
			return false;
		}
	}
	return true;
}
void floyd()
{
	for(int k=1;k<=n;k++)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(map[i][j]>map[i][k]+map[k][j])
				{
					map[i][j]=map[i][k]+map[k][j];
				}
			}
		}
	}
}
int main()
{
	int ques;
	while(~scanf("%d%d",&n,&m),n+m)
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(i==j) map[i][j]=0;
				else map[i][j]=inf;
			}
		} 
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				for(int k=1;k<=m;k++)
				{
					scanf("%d",&g[i][j][k]);
				}
			}
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(i==j) continue;
				mul(g[i],g[j]);
				for(int k=1;k<=n;k++)
				{
					if(k==i||k==j||map[i][k]==1) continue;
					if(judge(k))
					map[i][k]=1;
				}
			}
		}
		floyd();
		scanf("%d",&ques);
		while(ques--)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			if(map[a][b]!=inf) printf("%d\n",map[a][b]);
			else printf("Sorry\n");
		}
	}
	return 0;
}



你可能感兴趣的:(HDU 2807 The Shortest Path 把矩阵抽象成点+Floyd)