当前位置:网站首页>L3-007 天梯地图(测试点2卡住了可以看下)
L3-007 天梯地图(测试点2卡住了可以看下)
2022-08-08 04:06:00 【Cod_ing】
一道Dijkstra的模板题,关于测试点2通不过的问题是没有考虑题目输出的额外的要求:
如果最快到达路线不唯一,则输出几条最快路线中最短的那条,题目保证这条路线是唯一的。而如果最短距离的路线不唯一,则输出途径节点数最少的那条,题目保证这条路线是唯一的。
1、如果耗费的时间最短的结果有多个,那么选择路径长度最短的。
2、如果路径最短的结果有多个,那么选择经过节点最少的。
本题要求你实现一个天梯赛专属在线地图,队员输入自己学校所在地和赛场地点后,该地图应该推荐两条路线:一条是最快到达路线;一条是最短距离的路线。题目保证对任意的查询请求,地图上都至少存在一条可达路线。
输入格式:
输入在第一行给出两个正整数N(2 ≤ N ≤ 500)和M,分别为地图中所有标记地点的个数和连接地点的道路条数。随后M行,每行按如下格式给出一条道路的信息:
V1 V2 one-way length time
其中V1和V2是道路的两个端点的编号(从0到N-1);如果该道路是从V1到V2的单行线,则one-way为1,否则为0;length是道路的长度;time是通过该路所需要的时间。最后给出一对起点和终点的编号。
输出格式:
首先按下列格式输出最快到达的时间T和用节点编号表示的路线:
Time = T: 起点 => 节点1 => … => 终点
然后在下一行按下列格式输出最短距离D和用节点编号表示的路线:
Distance = D: 起点 => 节点1 => … => 终点
如果最快到达路线不唯一,则输出几条最快路线中最短的那条,题目保证这条路线是唯一的。而如果最短距离的路线不唯一,则输出途径节点数最少的那条,题目保证这条路线是唯一的。
如果这两条路线是完全一样的,则按下列格式输出:
Time = T; Distance = D: 起点 => 节点1 => … => 终点
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int MaxSize = 1e5 + 5;;
struct Edge {
int v, len, tm;
};
vector<Edge> E[505];
vector<int> ans[2];
int Ans[2];
bool vis[505];
int dis[505];
int cnt[505];
int pre[505];
void init() {
memset(vis, false, sizeof(vis));
memset(dis, 0x3f, sizeof(dis));
memset(cnt, 0, sizeof(cnt));
memset(pre, -1, sizeof(pre));
}
void Dijkstra_len(int v1, int v2) {
init();
dis[v1] = 0;
queue<int> Q;
int v, u,w;
Q.push(v1);
while (!Q.empty()) {
v = Q.front(); Q.pop();
if (vis[v]) continue;
vis[v] = true;
for (int i = 0; i < E[v].size(); i++) {
u = E[v][i].v, w = E[v][i].len;
if (dis[u] > dis[v] + w) {
Q.push(u);
dis[u] = dis[v] + w;//dis[x]表示起点到x的路程
cnt[u] = cnt[v] + 1;//cnt[x]表示起点到x的节点数
pre[u] = v;
}
else if (dis[u] == dis[v] + w && cnt[v] + 1 < cnt[u]) {
cnt[u] = cnt[v] + 1;
pre[u] = v;
}
}
}
int ends = v2;
while (ends != v1) {
ans[0].push_back(ends);
ends = pre[ends];
}
ans[0].push_back(ends);
reverse(ans[0].begin(), ans[0].end());
Ans[0] = dis[v2];
}
void Dijkstra_time(int v1, int v2) {
init();
queue<int> Q;
Q.push(v1);
dis[v1] = 0;
int u, v, w,w1;
while (!Q.empty()) {
v = Q.front(); Q.pop();
if (vis[v]) continue;
vis[v] = true;
for (int i = 0; i < E[v].size(); i++) {
u = E[v][i].v, w = E[v][i].tm, w1 = E[v][i].len;
if (dis[u] > dis[v] + w) {
Q.push(u);
dis[u] = dis[v] + w;//dis[x]表示起点到x的耗时
cnt[u] = cnt[v] + w1;//cnt[x]表示起点到x的路程
pre[u] = v;
}
else if (dis[u] == dis[v] + w && cnt[v] + w1 < cnt[u]) {
cnt[u] = cnt[v] + w1;
pre[u] = v;
}
}
}
int ends = v2;
while (ends != v1) {
ans[1].push_back(ends);
ends = pre[ends];
}
ans[1].push_back(ends);
reverse(ans[1].begin(), ans[1].end());
Ans[1] = dis[v2];
}
void output(int v1,int v2) {
if (ans[0] == ans[1]) {
printf("Time = %d; Distance = %d: ", Ans[1], Ans[0]);
for (int i = 0; i < ans[0].size(); i++) {
cout << ans[0][i];
if (i != ans[0].size() - 1) cout << " => ";
}
}
else {
printf("Time = %d: ", Ans[1]);
for (int i = 0; i < ans[1].size(); i++) {
cout << ans[1][i];
if (i != ans[1].size() - 1) cout << " => ";
}
cout << endl;
printf("Distance = %d: ", Ans[0]);
for (int i = 0; i < ans[0].size(); i++) {
cout << ans[0][i];
if (i != ans[0].size() - 1) cout << " => ";
}
}
}
int main() {
int N, M,v1,v2,one,len,tm;
cin >> N >> M;
while (M--) {
cin >> v1 >> v2 >> one >> len >> tm;
E[v1].push_back({
v2,len,tm });
if (!one) E[v2].push_back({
v1, len, tm });
}
cin >> v1 >> v2;
Dijkstra_len(v1, v2);
Dijkstra_time(v1, v2);
output(v1, v2);
return 0;
}
总结:对于这种模板题需要熟练掌握模板,这样才能在做题的时候灵活变化。下面给出基本模板:
使用邻接矩阵存储权值
void Dijkstra_(int bg) {
memset(vis, false, sizeof(vis));
memset(dis, 0x3f, sizeof(dis));
for (int i = 0; i < N; i++) {
if (A[bg][i] < 0x3f3f3f3f) dis[i] = A[bg][i];
}
int t, minn;
vis[n] = true;
for (int i = 0; i < N; i++) {
minn = 0x3f3f3f3f;
for (int j = 0; j < N; j++) {
if (!vis[j] && minn > dis[j]) {
minn = dis[j];
t = j;
}
}
vis[t] = true;
for (int j = 0; j < N; j++) {
if (!vis[j] && dis[j] > dis[t] + A[t][j]) {
dis[j] = dis[t] + A[t][j];
}
}
}
}
使用邻接表存储权值
void Dijkstra(int bg) {
memset(vis, false, sizeof(vis));
memset(dis, 0x3f, sizeof(dis));
memset(pre, -1, sizeof(pre));
queue<int> Q;
Q.push(bg);
int w, u, v;
while (!Q.empty()) {
u = Q.front(); Q.pop();
if (vis[u]) continue;
vis[u] = true;
for (int i = 0; i < A[u].size(); i++) {
v = A[u][i].v, w = A[u][i].w;
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
pre[v] = u;
}
}
}
}
边栏推荐
- JS 怎么使用十六进制保存100位状态的问题
- 开发如何尽可能的避免BUG
- 产品经理必备的19类工具网站
- 【直播回顾】昇思MindSpore易用性SIG2022上半年回顾总结
- LeetCode_485_Maximum number of consecutive 1s
- C language minesweeping
- Build a personal network disk using z-file and Qiniu cloud object storage
- The type of block in the database buffer cache
- 依赖导致原则改善代码
- KDD'22 | CausalMTA: Unbiased Advertising Multi-Touch Attribution Technology Based on Causal Inference
猜你喜欢
随机推荐
NetCore使用Dapper查询数据
vulnhub-DC-3靶机渗透记录
内修昇思MindSpore AI框架,外重行业汇聚,华为大模型的不平凡之路
leetcode: 122. 买卖股票的最佳时机 II
让你的文字被更多人看到:来投稿吧,稿酬靠谱!
Vulfocus Shooting Range Scenario Mode - Intranet Dead End
依赖导致原则改善代码
失业在家的6个月,我通过外包全款买了房:你看不起的行业,往往很赚钱
MySQL from entry to entry [20W word collection]
Young freshmen who yearn for open source | The guide to avoiding pits from open source to employment is here!
数据在内存如何分布的?
数据标注平台doccano----简介、安装、使用、踩坑记录
拒绝“内卷”跃迁软件测试最大门槛,我是如何从月薪8K到15K的?
C语言 扫雷
The difference between orElse and orElseGet in Optional
Exercise equipment responsive pbootcms template class web site
关于 globalThis is not defined 报错问题
【opencv】opencv开发包简介
剑指Offer 18.删除链表的节点
VSCode打开 C(嵌入式) 工程的一些记录









