题目描述
给一张无向图G(U, E), 询问任意两点的最短距离。
输入
第一行两个整数n,m表示图中结点数和边的数量, 结点从1到n编号。
接下来m行,每行三个整数u,v,w表示u,v之间有一条距离为w的边。
接下来一行一个整数q,表示询问次数。
接下来q行每行两个整数u,v,表示询问u到v的最短距离, 如果u不能到达v输出-1。
数据范围:n <= 100, m <= 5000, q <= 10000, 0 < w <= 1000。
输出对应输出q行答案。
样例输入
5 10
1 2 1
2 5 10
1 3 2
1 4 4
1 5 6
2 3 4
2 4 3
3 4 1
3 5 4
4 5 2
5
1 4
3 5
2 3
4 2
5 2
样例输出
3
3
3
3
5
我的TIPS:
这里简要的提及一下How to deal with it.第一步,先给定一个二维数组(虽然这玩意的标准说法是图的邻接矩阵),数组arr[x][y]的意思是从点x到点y,将对角线上的值都设为0(x到x的距离是0),其他值都设为无穷大(点x到另一个点y之间没有通路设为无穷大,那个0x3f3f3f3f的意思是无穷大),第二步,接着将题干中给的距离进入数组中重新更改。第三步,在比较中,最好的方法是从点x到点y直接有通路;但此时我们发现从点x到点z,再从点z到点y的距离比直接从点x到点y的距离短,那我们就重新更正点x到点y的距离,也就是数组arr[x][y]的值为arr[x][z]+arr[z][y],以此类推。
#include<iostream>
#include<cstring>
using namespace std;
const int temp=0x3f3f3f3f;
int arr[400][400];//这题在OJ系统里给的n的范围并不是0~100,坑死人了
int n,m;//n为点的个数,m为边的条数
int main()
{ while(cin>>n>>m)
{ for(int i=0;i<400;i++)//第一步,我们将整个二维数组的元素设置为无穷大或0
{ for(int j=0;j<400;j++)
{ arr[i][j]=temp;
if(i==j){arr[i][j]=0;}
}
}
int a,b,c;
for(int i=1;i<=m;i++)//第二步,我们将测试用例中的边的数据进行记录
{ cin>>a>>b>>c;
if(c<arr[a][b])
{arr[a][b]=arr[b][a]=c;}
}
for(int k=1;k<=n;k++)//第三步,弗洛伊德算法
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(arr[i][j]>arr[i][k]+arr[k][j]&&arr[i][k]<temp&&arr[k][j]<temp)
arr[i][j]=arr[i][k]+arr[k][j];
int q;
while(cin>>q&&q>=0)
{ for(int i=1;i<=q;i++)
{
int x,y;
cin>>x>>y;
if(arr[x][y]>=temp)
{cout<<"-1"<<endl;}
else
{cout<<arr[x][y]<<endl;}
}
}
}
return 0;
}
当代学子真是被压榨的对象,祝各位考研和保研顺利,早离开早好。