一:HDU2807
The Shortest Path
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
//矩阵和最短路,最短路毫无疑问是floyd算法,矩阵如果用普通的矩阵:矩阵乘法O(n3),矩阵比较O(m2),会超时。
所以要优化矩阵,再增添一个m*1的矩阵remat[n],remat[i]=matrix[i]* ,题目要求的A*B=C就变成了remat[A的下标]*B=remar[C的下标],这样乘法的复杂度就变成了O(n2),比较复杂度变成了O[m]。代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#define INF 0xffff
using namespace std;
int n,m;
struct matrix
{
int mp[85][85];
}mat[85];
int edge[85][85];
struct rematrix
{
int a[85];
}remat[85];
void ok(int x,int y)
{
for(int i=1;i<=m;i++)
if(remat[0].a[i]!=remat[y].a[i])return ;
edge[x][y]=1;
}
void cal(int x,int y)
{
for(int i=1;i<=m;i++)
{
remat[0].a[i]=0;
for(int j=1;j<=m;j++)
{
remat[0].a[i]+=mat[x].mp[i][j]*remat[y].a[j];
}
}
for(int i=1;i<=n;i++)
if(i!=x&&i!=y)ok(x,i);
}
void floyd()
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
edge[i][j]=min(edge[i][j],edge[i][k]+edge[k][j]);
}
int main()
{
while(~scanf("%d%d",&n,&m)&&n&&m)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
edge[i][j]=INF;
edge[i][i]=0;
}//printf("***\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
remat[i].a[j]=0;
for(int k=1;k<=m;k++)
{
scanf("%d",&mat[i].mp[j][k]);
remat[i].a[j]+=mat[i].mp[j][k]*k;
}
}
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j)cal(i,j);
floyd();
int q;
cin>>q;
while(q--)
{
// printf("****\n");
int x,y;
scanf("%d%d",&x,&y);
if(edge[x][y]<INF)printf("%d\n",edge[x][y]);
else printf("Sorry\n");
}
}
return 0;
}
二:hdu1599
find the mincost route
杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须满足K>2,就是说至除了出发点以外至少要经过2个其他不同的景区,而且不能重复经过同一个景区。现在8600需要你帮他找一条这样的路线,并且花费越少越好。
Input
第一行是2个整数N和M(N <= 100, M <= 1000),代表景区的个数和道路的条数。
接下来的M行里,每行包括3个整数a,b,c.代表a和b之间有一条通路,并且需要花费c元(c <= 100)。
Output
对于每个测试实例,如果能找到这样一条路线的话,输出花费的最小值。如果找不到的话,输出"It's impossible.".
Sample Input
3 3 1 2 1 2 3 1 1 3 1 3 3 1 2 1 1 2 3 2 3 1
Sample Output
3 It's impossible.
//floyd算法
//同一条边输入两次取最小
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
int d[105][105];
int mp[105][105];
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i == j)
{
mp[i][j] = d[i][j] = 0;
}
else
{
mp[i][j] = d[i][j] = 0xffff;
}
}
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
mp[a][b]=mp[b][a]=d[a][b]=d[b][a]=min(d[a][b],c);
}
int ans=0xffff;
for(int k=1;k<=n;k++)
{
for(int i=1;i<k;i++)
for(int j=i+1;j<k;j++)
ans=min(ans,d[i][j]+mp[j][k]+mp[k][i]);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
if(ans==0xffff)
printf("It's impossible.\n");
else printf("%d\n",ans);
}
return 0;
}