【题目描述】
平面上有n个点(n≤100),每个点的坐标均在-10000~10000之间。其中的一些点之间有连线。
若有连线,则表示可从一个点到达另一个点,即两点间有通路,通路的距离为两点间的直线距离。现在的任务是找出从一点到另一点之间的最短路径。
【输入】
共n+m+3行,其中:
第一行为整数n。
第2行到第n+1行(共n行) ,每行两个整数x和y,描述了一个点的坐标。
第n+2行为一个整数m,表示图中连线的个数。
此后的m 行,每行描述一条连线,由两个整数i和j组成,表示第i个点和第j个点之间有连线。
最后一行:两个整数s和t,分别表示源点和目标点。
【输出】
一行,一个实数(保留两位小数),表示从s到t的最短路径长度。
【输入样例】
5 0 0 2 0 2 2 0 2 3 1 5 1 2 1 3 1 4 2 5 3 5 1 5
【输出样例】
3.41
1.Floyed-Warshall算法 O(N3) n<=500
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a[101][3], n,i,j,k,x,y,m,s,e; 4 double f[101][101]; 5 int main() 6 { 7 cin >> n; 8 for (i = 1; i <= n; i++) 9 cin >> a[i][1] >> a[i][2]; //第i个点的坐标 10 cin >> m; 11 memset(f,0x3f,sizeof(f)); //初始化f数组为最大值 12 for (i = 1; i <= m; i++) //预处理出x、y间距离 13 { 14 cin >> x >> y; //pow(x,y)表示x^y,其中x,y必须为double类型,要用cmath库 15 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)); 16 } 17 cin >> s >> e; 18 for (k = 1; k <= n; k++) //floyed 最短路算法 19 for (i = 1; i <= n; i++) 20 for (j = 1; j <= n; j++) 21 if ((i != j) && (i != k) && (j != k) && (f[i][k]+f[k][j] < f[i][j])) 22 f[i][j] = f[i][k] + f[k][j]; 23 printf("%.2lf\n",f[s][e]); 24 return 0; 25 }
2.Dijkstra算法O (N2) 未优化n<=5000 贪心
1 #include<bits/stdc++.h> 2 using namespace std; 3 int a[101][3] ,f[101][101];; 4 double c[101]; 5 bool b[101]; 6 int n,i,j,k,x,y,m,s,e; 7 double minl; 8 double maxx = 1e30; 9 int main() 10 { 11 cin >> n; 12 for (i = 1; i <= n; i++) 13 cin >> a[i][1] >> a[i][2]; 14 for (i = 1; i <= n; i++) 15 for(j = 1; j <= n; j++) 16 f[i][j] = maxx; //f数组初始化最大值 17 cin >> m; 18 for (i = 1; i <= m; i++) //预处理x.y间距离f[x][y] 19 { 20 cin >> x >> y; 21 f[x][y] = f[y][x] = sqrt(pow(double(a[x][1]-a[y][1]),2)+pow(double(a[x][2]-a[y][2]),2)); 22 } 23 cin >> s >> e; 24 for (i = 1; i <= n; i++) 25 c[i] = f[s][i]; //初始化 26 memset(b,false,sizeof(b)); //dijkstra 最短路 27 b[s] = true; //源点 28 c[s] = 0; 29 for (i = 1; i <= n-1; i++) 30 { 31 minl = maxx; //贪心找最小 32 k = 0; 33 for (j = 1; j <= n; j++) //查找可以更新的点 34 if ((! b[j]) && (c[j] < minl)) 35 { 36 minl = c[j]; 37 k = j; 38 } 39 if (k == e) break; //小优化 40 b[k] = true; 41 for (j = 1; j <= n; j++) 42 if (c[k] + f[k][j] < c[j]) 43 c[j] = c[k] + f[k][j]; 44 } 45 printf("%.2lf\n",c[e]); 46 return 0; 47 }
堆优化后Dijkstra算法O (NlogN)
for (i = 1; i <= n-1; i++) { minl = maxx; k = 0; for (j = 1; j <= n; j++) //查找可以更新的点 if ((! b[j]) && (c[j] < minl)) { minl = c[j]; k = j; } if (k == e) break; b[k] = true; for (j = 1; j <= n; j++) if (c[k] + f[k][j] < c[j]) c[j] = c[k] + f[k][j]; }
邻接表加堆优化
也可以另定一个函数
3.Bellman-Ford算法O(NE)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 double a[101][3],dis[1001],w[1001],min1; 6 int n,m,x,y,k,f[1001][3],s,t; // f数组储存第i条边的起点与终点 7 bool b[101]; 8 cin>>n; 9 for (int i=1;i<=n;i++) 10 scanf("%lf%lf",&a[i][1],&a[i][2]); 11 cin>>m; 12 for (int i=1;i<=m;i++) //初始化数组dis 13 dis[i]=0x7fffffff/3; 14 for (int i=1;i<=m;i++) 15 { 16 scanf("%d%d",&x,&y); 17 f[i][1]=x; f[i][2]=y; 18 w[i]=sqrt(pow(a[x][1]-a[y][1],2)+pow(a[x][2]-a[y][2],2)); 19 } 20 cin>>s>>t; 21 dis[s]=0; 22 for (int i=1;i<=n;i++) //ford算法主体 23 for (int j=1;j<=m;j++) 24 { 25 if (dis[f[j][1]]+w[j]<dis[f[j][2]]) dis[f[j][2]]=dis[f[j][1]]+w[j]; 26 if (dis[f[j][2]]+w[j]<dis[f[j][1]]) dis[f[j][1]]=dis[f[j][2]]+w[j]; 27 } 28 printf("%.2f",dis[t]); 29 }
4、SPFA算法O(kE)