【题目链接】

ybt 1342:【例4-1】最短路径问题

【题目考点】

1. 图论 最短路径

图中有V个顶点E条边,最短路径算法时间复杂度:

  • 朴素Dijkstra算法:O(V2)O(V^2)O(V2)
  • Dijkstra堆优化算法:O(ElogE)O(ElogE)O(ElogE)
  • SPFA算法:一般情况下O(kE)O(kE)O(kE),k为顶点平均入队次数,最坏情况下O(VE)O(VE)O(VE)
  • Floyd算法: O(V3)O(V^3)O(V3)

空间复杂度:

  • 邻接矩阵:O(V2)O(V^2)O(V2)
  • 邻接表:O(V+E)O(V+E)O(V+E)

【解题思路】

该题输入各顶点坐标,以及每条边是哪两个点相连。那么需要我们手动计算两点间距离,作为这条边的权值。使用两点间距离公式:(x1,x2)(x_1,x_2)(x1​,x2​)到(y1,y2)(y_1,y_2)(y1​,y2​)的距离
(x1−x2)2+(y1−y2)2\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}(x1​−x2​)2+(y1​−y2​)2​
建图完成后,就是一个标准的求最短路径问题。
注意:表示距离的数组,边的权值,在该问题中都是double类型的。
double类型的数组dis,将元素都设为大约为1.08∗10161.08*10^{16}1.08∗1016的较大值,可以写memset(dis, 0x43, sizeof(dis));
该题顶点数目为100,那么边最多10000个。用哪种算法及存储结构都可以。
该题顶点个数较少,可以使用Floyd算法及邻接矩阵。本题主要展示最短路径算法使用邻接矩阵时的写法。
如想看邻接表的写法,可以参考我在同一章节下其他题目的题解。

【题解代码】

解法1:Floyd算法+邻接矩阵

#include<bits/stdc++.h>
using namespace std;
#define N 105
struct Cord
{int x, y;
};
double edge[N][N];
int n, m, st, te;//st:起点 te:终点
double dis[N][N];//dis[i][j]:顶点i到顶点j的最短距离
Cord ver[N];//保存每个顶点的坐标
double getDis(Cord a, Cord b)//获取点a到点b两点间直线距离
{return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void init()
{int f, t;cin >> n;for(int i = 1; i <= n; ++i)cin >> ver[i].x >> ver[i].y;cin >> m;for(int i = 1; i <= m; ++i){cin >> f >> t;edge[f][t] = edge[t][f] = getDis(ver[f], ver[t]);//顶点f到顶点t的边的权值为点f到点t的直线距离 }cin >> st >> te;
}
void floyd()
{memset(dis, 0x43, sizeof(dis));//这样可以使dis中每个元素的值大约为1.08e16,是一个较大值 for(int i = 1; i <= n; ++i)for(int j = 1; j <= n; ++j)if(edge[i][j] > 0)dis[i][j] = edge[i][j];for(int k = 1; k <= n; ++k)for(int i = 1; i <= n; ++i)for(int j = 1; j <= n; ++j)if(dis[i][j] > dis[i][k] + dis[k][j])dis[i][j] = dis[i][k] + dis[k][j];
}
int main()
{init();floyd();cout << fixed << setprecision(2) << dis[st][te];return 0;
}

解法2:朴素Dijkstra算法+邻接矩阵

#include<bits/stdc++.h>
using namespace std;
#define N 105
struct Cord
{int x, y;
};
double edge[N][N];
int n, m, st, te;//st:起点 te:终点
double dis[N];//dis[i]:st到顶点i的最短距离
bool vis[N];
Cord ver[N];//保存每个顶点的坐标
double getDis(Cord a, Cord b)//获取点a到点b两点间直线距离
{return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void init()
{int f, t;cin >> n;for(int i = 1; i <= n; ++i)cin >> ver[i].x >> ver[i].y;cin >> m;for(int i = 1; i <= m; ++i){cin >> f >> t;edge[f][t] = edge[t][f] = getDis(ver[f], ver[t]);//顶点f到顶点t的边的权值为点f到点t的直线距离 }cin >> st >> te;
}
void dijkstra()
{memset(dis, 0x43, sizeof(dis));//这样可以使dis中每个元素的值大约为1.08e16,是一个较大值dis[st] = 0; for(int k = 1; k <= n; ++k){int u = 0;for(int i = 1; i <= n; ++i)if(vis[i] == false && (u == 0 || dis[i] < dis[u]))u = i;vis[u] = true;for(int v = 1; v <= n; ++v){if(edge[u][v]){double w = edge[u][v];if(vis[v] == false && dis[v] > dis[u] + w)dis[v] = dis[u] + w;}}}
}
int main()
{init();dijkstra();cout << fixed << setprecision(2) << dis[te];return 0;
}

解法3:SPFA算法+邻接矩阵

#include<bits/stdc++.h>
using namespace std;
#define N 105
struct Cord
{int x, y;
};
double edge[N][N];
int n, m, st, te;//st:起点 te:终点
double dis[N];//dis[i]:st到顶点i的最短距离
bool vis[N]; //vis[i]:i是否在队列内
Cord ver[N];//保存每个顶点的坐标
double getDis(Cord a, Cord b)//获取点a到点b两点间直线距离
{return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void init()
{int f, t;cin >> n;for(int i = 1; i <= n; ++i)cin >> ver[i].x >> ver[i].y;cin >> m;for(int i = 1; i <= m; ++i){cin >> f >> t;edge[f][t] = edge[t][f] = getDis(ver[f], ver[t]);//顶点f到顶点t的边的权值为点f到点t的直线距离 }cin >> st >> te;
}
void spfa()
{memset(dis, 0x43, sizeof(dis));//这样可以使dis中每个元素的值大约为1.08e16,是一个较大值queue<int> que;dis[st] = 0; que.push(st);vis[st] = true;while(que.empty() == false){int u = que.front();que.pop();vis[u] = false;for(int v = 1; v <= n; ++v){if(edge[u][v]){double w = edge[u][v];if(dis[v] > dis[u] + w){dis[v] = dis[u] + w;if(vis[v] == false){vis[v] = true;que.push(v);} }}}}
}
int main()
{init();spfa();cout << fixed << setprecision(2) << dis[te];return 0;
}

解法4:Dijkstra堆优化算法+邻接表

#include<bits/stdc++.h>
using namespace std;
#define N 105
struct Cord
{int x, y;
};
struct Edge
{int t;double w;Edge(){}Edge(int a, double b):t(a),w(b){}
};
struct Pair
{int u;//u:顶点double d;//距离 Pair(){}Pair(int a, double b):u(a),d(b){}bool operator < (const Pair &b) const{return b.d < d;}
};
vector<Edge> edge[N];
int n, m, st, te;//st:起点 te:终点
double dis[N];//dis[i]:st到顶点i的最短距离
bool vis[N]; //vis[i]:i是否在队列内
Cord ver[N];//保存每个顶点的坐标
double getDis(Cord a, Cord b)//获取点a到点b两点间直线距离
{return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
void init()
{int f, t;double w;cin >> n;for(int i = 1; i <= n; ++i)cin >> ver[i].x >> ver[i].y;cin >> m;for(int i = 1; i <= m; ++i){cin >> f >> t;w = getDis(ver[f], ver[t]); edge[f].push_back(Edge(t, w));edge[t].push_back(Edge(f, w));        }cin >> st >> te;
}
void dijkstra()
{priority_queue<Pair> pq;memset(dis, 0x43, sizeof(dis));//这样可以使dis中每个元素的值大约为1.08e16,是一个较大值dis[st] = 0;pq.push(Pair(st, 0));while(pq.empty() == false){int u = pq.top().u;pq.pop();if(vis[u])//如果顶点u已经访问过,则跳过 continue;vis[u] = true;for(int i = 0; i < edge[u].size(); ++i) {int v = edge[u][i].t;double w = edge[u][i].w; if(vis[v] == false && dis[v] > dis[u] + w)//松弛{dis[v] = dis[u] + w;pq.push(Pair(v, dis[v]));}}}
}
int main()
{init();dijkstra();cout << fixed << setprecision(2) << dis[te];return 0;
}

信息学奥赛一本通 1342:【例4-1】最短路径问题相关推荐

  1. 【例1】 0/1背包《信息学奥赛一本通》【解法一】 02

    /* [例1] 0/1背包<信息学奥赛一本通>[解法一] 02 http://ybt.ssoier.cn:8088/problem_show.php?pid=1267 */ #includ ...

  2. 【例8】合唱队形(《信息学奥赛一本通第五版》)

    /* [例8]合唱队形(<信息学奥赛一本通第五版>) http://ybt.ssoier.cn:8088/problem_show.php?pid=1264 [问题描述] N位同学站成一排 ...

  3. 信息学奥赛一本通 2021:【例4.6】最大公约数

    [题目链接] ybt 2021:[例4.6]最大公约数 [题目考点] 1. while循环 2. 求最大公约数 辗转相减法 辗转相除法 [解题思路] 解法1:枚举 取较小数字,从该数字的值开始从大到小 ...

  4. 信息学奥赛一本通(2032:【例4.18】分解质因数)

    2032:[例4.18]分解质因数 时间限制: 1000 ms         内存限制: 65536 KB 提交数: 582     通过数: 376 [题目描述] 把一个合数分解成若干个质因数乘积 ...

  5. 信息学奥赛一本通——2062:【例1.3】电影票

    2062:[例1.3]电影票 时间限制: 1000 ms         内存限制: 65536 KB 提交数: 57341     通过数: 34230 [题目描述] 已知一位小朋友的电影票价是10 ...

  6. 信息学奥赛一本通 1278:【例9.22】复制书稿(book) | 洛谷 P1281 书的复制

    [题目链接] ybt 1278:[例9.22]复制书稿(book) 洛谷 P1281 书的复制 [题目考点] 1. 动态规划:线性动规 [解题思路] 该题可以抽象为:将由m个数字构成的序列分成k个子段 ...

  7. 信息学奥赛一本通1267:【例9.11】01背包问题(二维dp与滚动数组优化)

    [题目描述] 一个旅行者有一个最多能装 MM 公斤的背包,现在有 nn 件物品,它们的重量分别是W1,W2,...,WnW1,W2,...,Wn,它们的价值分别为C1,C2,...,CnC1,C2,. ...

  8. 信息学奥赛一本通C++语言-----2036:【例5.3】开关门

    [题目描述] 宾馆里有n(2≤n≤1000)n(2≤n≤1000) 个房间,从1∼n1∼n 编了号.第一个服务员把所有的房间门都打开了,第二个服务员把所有编号是22 的倍数的房间"相反处理& ...

  9. 信息学奥赛一本通——2068:【例2.6】鸡兔同笼

    大家好(๑╹◡╹)ノ" 这里是小蒟蒻 一天没更新了呢! 今天给大家带来<信息学奥赛一本通--2068:[例2.6]鸡兔同笼> 题目: 2068:[例2.6]鸡兔同笼 时间限制: ...

最新文章

  1. 计算机毕业生“一看就想留下”的简历
  2. 设计模式:选择排序(select sorting)
  3. android web 打印,Android设备WebView打印Console Log
  4. IIS - 用户 NT AUTHORITY\NETWORK SERVICE 登录失败解决方法
  5. 安卓手机浏览器排行_安卓手机双11性价比排行发布|拯救者手机发透明版|小米发大光圈手机镜头...
  6. object转class_从零并发框架(三)异步转同步注解+字节码增强代理实现
  7. 想拥有高清壁纸不用那么麻烦!
  8. mysql show db_mysql show操作
  9. 适应adblock plus 规则的简单正则表达式匹配
  10. 自协方差函数的Matlab实现
  11. 关于透明图像的滤色处理要注意的几个点
  12. pysaprk数据倾斜怎么解决?
  13. Oracle的OFA架构
  14. 阿里云服务器ECS搭建后台(Windows Server 2012R2)
  15. 微信输出日志在电脑桌面
  16. matlab中的covsfa什么意思,MALSAR1.1 多种多任务学习算法的工具箱 有代码有使 册 matlab版 238万源代码下载- www.pudn.com...
  17. 基于微博的舆情监控系统 JAVA SSM MySQL
  18. DenseNet 算法
  19. 全国工企专利匹配数据(1998-2014)
  20. Eclipse各个版本及区别

热门文章

  1. 积极向上,努力工作,提高能力,提高战斗力,保持热情,保持创业热情。
  2. 为List配置一个搜索按钮
  3. 进厂打工的大学生:每天站12个小时,4年存50万
  4. 详解6G系统数据治理方案的设计要点和原则
  5. 2021年,朋友圈都在传这8个视频
  6. 手把手教你做用户画像:3种标签类型、8大系统模块
  7. 图像sobel梯度详细计算过程_视频处理之Sobel【附源码】
  8. 记一次阿里面试题:都有哪些进程间通信方式?麻烦你不要再背了
  9. 华为发布会: 牛逼鸿蒙,吹水的大会
  10. maven 项目上传私服pom配置