原题传送门
题目描述
中山路店山店海,成了购物狂爱与愁大神的“不归之路”。中山路上有n(n<=100)家店,每家店的坐标均在-10000~10000之间。其中的m家店之间有通路。若有通路,则表示可以从一家店走到另一家店,通路的距离为两点间的直线距离。现在爱与愁大神要找出从一家店到另一家店之间的最短距离。你能帮爱与愁大神算出吗?
输入格式
共n+m+3行:
第1行:整数n
第2行~第n+1行:每行两个整数x和y,描述了一家店的坐标
第n+2行:整数m
第n+3行~第n+m+2行:每行描述一条通路,由两个整数i和j组成,表示第i家店和第j家店之间有通路。
第n+m+3行:两个整数s和t,分别表示原点和目标店
输出格式
仅一行:一个实数(保留两位小数),表示从s到t的最短路径长度。
输入输出样例
输入 #1
5
0 0
2 0
2 2
0 2
3 1
5
1 2
1 3
1 4
2 5
3 5
1 5
输出 #1
3.41
说明/提示
100%数据:n<=100,m<=1000
----------------------------------------------以下为题解部分-------------------------------------------------------------
分析:
这个题通过简单的分析题意,可以看出,显然是一道
SPFA的题(标签里的。。。。。。)
## But 本人太弱。。。。。。
NO Problem,无伤大雅
我们用Floyd来代替一下
这道题求任意两点之间的距离,众所周知,Floyd可以求任意两点的最短路,而且包括负边权,很强大。
先补充一点预备知识:
两点间距离公式:对于平面上两点(x1,y1),(x2,y2)他们的直线距离为
\[ \sqrt {(x1-x2)^2+(y1-y2)^2} \]
代码
#include
#include
#include
#include
using namespace std;
int a[101][3];
double f[101][101] //f[i][j]表示i点到j点的最短路;
int n,i,j,k,x,y,m,s,e;
int main(){
cin>>n;
for(i=1;i<=n;i++) cin>>a[i][1]>>a[i][2];
cin>>m;
memset(f,0x7f,sizeof(f)); //在没有已知连接不连接的情况下,对于有权值的图
//我们全部预处理成无限大
for(i=1;i<=m;i++){ //对于有连接的,我们用两点间距离公式更新距离
cin>>x>>y; //第二次输入有连接的
f[y][x]=f[x][y]=sqrt(pow(double(a[x][1]-a[y][1]),2)+pow(double(a[x][2]-a[y][2]),2));
}
cin>>s>>e; //原点和目标点
//Floyd关键部分
for(k=1;k<=n;k++){
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
if((i!=j)&&(i!=k)&&(j!=k)&&(f[i][k]+f[k][j]
但是我发现有一个更好的做法
优化核心思想
当原点和目标点之间有连线的时候,我们用两点之间距离公式求出来的距离就是最短路。我们可以加一个特判,即f[i][j]不是无穷大时,输出,结束。这样就可以少跑一边Floyd,对于某些数据,可以稍快一点。