题目设计:
你怀疑你的导航系统有时会选择低效的路线。
所以你决定收集一些关于你所在地区的道路系统的数据并编写一个程序,计算出从你的家到你所在地区的最短(综合道路长度)和最快(预期旅行时间)的路线。
为了使这一任务易于管理,你想出了一个简单的模型。道路系统道路系统由路口(数字从1到N)和连接它们的道路组成,每条道路都有一个限速(单位:km/h)和一个长度(单位:km)。
在其中一个路口转换道路既不耗费时间也不耗费距离。
为了简单起见,你还假设所有的道路都是双向的,并且你可以一直以限速行驶。
输入的内容包括
输出
例如:
第三组:
20 80
19 15 57 179
20 20 125 175
5 4 60 34
9 10 24 85
18 8 114 244
19 9 23 245
1 5 115 132
7 17 45 117
6 12 24 109
1 12 116 83
3 3 83 270
20 20 145 65
9 13 78 47
11 14 40 152
9 15 79 70
18 9 72 101
19 5 105 282
2 3 120 90
20 13 105 186
2 4 72 145
13 18 103 90
1 3 26 143
19 13 45 7
5 14 39 295
9 7 74 218
15 5 73 131
6 15 79 255
6 15 56 113
14 5 40 157
17 17 57 216
17 14 106 260
18 9 121 201
7 11 76 25
14 17 20 144
10 6 49 285
6 16 88 95
6 4 82 96
10 16 121 187
19 11 100 294
6 9 129 241
4 4 90 99
11 15 79 130
5 8 95 108
19 15 29 285
19 20 122 280
19 13 76 13
12 16 67 88
18 10 107 56
2 18 147 300
6 15 27 130
16 6 80 28
8 5 101 96
16 16 76 130
12 3 134 1
17 4 145 284
14 9 24 203
5 13 39 140
12 9 116 254
5 12 141 52
16 3 68 95
17 1 44 14
12 20 62 161
18 16 129 72
16 18 117 114
20 17 128 271
2 1 92 255
1 19 74 115
15 2 57 240
18 7 41 140
14 1 107 280
4 6 66 205
6 10 60 209
17 2 112 42
8 2 45 14
7 16 59 33
13 16 40 270
17 6 41 59
4 13 57 245
19 11 55 97
2 8 115 80
10
2 s
15 f
7 s
17 f
8 f
9 f
17 s
16 f
2 s
3 f
输出:
56 km
2.87883212 h
131 km
0.31818182 h
1.00429293 h
2.31217371 h
14 km
2.02895008 h
56 km
0.72297993 h
关于这道题应该要用到Dijkstra算法或者Moore-Bellman-Ford 算法?希望可以给个详细点的代码,谢谢!
学到的算法如下代码
void dijkstra_set (int s, int n) {
fill (d, d + n + 1, INF ) ;
d[s] = 0;
set <pair <int , int > > dst ;
dst . insert ({d[s], s}) ;
while (! dst. empty () ) {
int v = dst . begin () -> second ;
dst . erase ( dst . begin () );
for ( auto e: edges [v])
if (d[v] + e. cost < d[e.u]) {
dst . erase ({d[e.u], e.u}) ;
d[e.u] = d[v] + e. cost ;
dst . insert ({d[e.u], e.u}) ;
}
}
}
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 100;
struct Edge{
int next;
int to;
int len;
int speed;
}edge[MAXN];
int cnt;
int head[MAXN];
void Add_Edge(int u, int v, int speed, int len){
edge[cnt].next = head[u];
edge[cnt].to = v;
edge[cnt].speed = speed;
edge[cnt].len = len;
head[u] = cnt++;
}
int dis[MAXN];
struct st{
int id;
int dis;
bool operator < (const st &B)const{
return dis > B.dis;
}
};
int vis[MAXN];
const int INF = 0x3f3f3f3f;
void dijkstra(int s){
dis[s] = 0;
priority_queue<st> q;
q.push(st{s, dis[s]});
while(!q.empty()){
auto u = q.top();
q.pop();
if(vis[u.id]) continue;
vis[u.id] = 1;
for(int i=head[u.id];~i;i=edge[i].next){
int v = edge[i].to;
if(!vis[v] && dis[u.id] + edge[i].len < dis[v]){
dis[v] = dis[u.id] + edge[i].len;
q.push(st{v, dis[v]});
}
}
}
}
const double eps = 1e-10;
int dcmp(double x){
if(fabs(x) < eps) return 0;
return x < 0 ? -1 : 1;
}
struct st2{
int id;
double t;
bool operator < (const st2 &B)const{
return dcmp(t - B.t) > 0;
}
};
double dis2[MAXN];
const double INF2 = 999999999.0;
void dijkstra2(int s){
dis2[s] = 0.0;
priority_queue<st2> q;
q.push(st2{s, dis2[s]});
while(!q.empty()){
auto u = q.top();
q.pop();
if(vis[u.id]) continue;
vis[u.id] = 1;
for(int i=head[u.id];~i;i=edge[i].next){
int v = edge[i].to;
if(!vis[v] && dcmp(dis2[v] - dis2[u.id] - edge[i].len * 1.0 / edge[i].speed) > 0){
dis2[v] = dis2[u.id] + edge[i].len * 1.0 / edge[i].speed;
q.push(st2{v, dis2[v]});
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m;
cin >> n >> m;
memset(head, -1, sizeof head);
memset(dis, 0x3f, sizeof dis);
for(int i=0;i<m;i++){
int u, v, speed, len;
cin >> u >> v >> speed >> len;
Add_Edge(u, v, speed, len);
Add_Edge(v, u, speed, len);
}
int q;
dijkstra(1);
memset(vis, 0, sizeof vis);
for(int i=0;i<=n;i++) dis2[i] = INF2;
dijkstra2(1);
cin >> q;
while(q--){
int j;
char c;
cin >> j >> c;
if(c == 's'){
if(dis[j] == INF) cout << "IMPOSSIBLE\n";
else cout << dis[j] << ' ' << "km\n";
}else{
if(dcmp(dis2[j] - INF2) == 0) cout << "IMPOSSIBLE\n";
else cout << fixed << setprecision(8) << dis2[j] << ' ' << "h\n";
}
}
return 0;
}
看不太懂,看不出如果是一道图论题,那么图的节点和矩应该如何用数据结构标记?连通性和最短矩是图论的标准根算,速度有关问题是讨论了键强度的泛生问题。实际的图论解答中,键强度是优势考量因素,赋权比速度解优先。
是否为一道数组题?可以考虑一下以下数组:
//{7,11,14,17,18,19};
//{22,24,26,27,28,29};
//{51,55,56,57,58,59};
//{60,62,66,67,68,69};
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 2e5 + 100;
struct Edge{
int next;
int to;
int len;
int speed;
}edge[MAXN];
int cnt;
int head[MAXN];
void Add_Edge(int u, int v, int speed, int len){
edge[cnt].next = head[u];
edge[cnt].to = v;
edge[cnt].speed = speed;
edge[cnt].len = len;
head[u] = cnt++;
}
int dis[MAXN];
struct st{
int id;
int dis;
bool operator < (const st &B)const{
return dis > B.dis;
}
};
int vis[MAXN];
const int INF = 0x3f3f3f3f;
void dijkstra(int s){
dis[s] = 0;
priority_queue<st> q;
q.push(st{s, dis[s]});
while(!q.empty()){
auto u = q.top();
q.pop();
if(vis[u.id]) continue;
vis[u.id] = 1;
for(int i=head[u.id];~i;i=edge[i].next){
int v = edge[i].to;
if(!vis[v] && dis[u.id] + edge[i].len < dis[v]){
dis[v] = dis[u.id] + edge[i].len;
q.push(st{v, dis[v]});
}
}
}
}
const double eps = 1e-10;
int dcmp(double x){
if(fabs(x) < eps) return 0;
return x < 0 ? -1 : 1;
}
struct st2{
int id;
double t;
bool operator < (const st2 &B)const{
return dcmp(t - B.t) > 0;
}
};
double dis2[MAXN];
const double INF2 = 999999999.0;
void dijkstra2(int s){
dis2[s] = 0.0;
priority_queue<st2> q;
q.push(st2{s, dis2[s]});
while(!q.empty()){
auto u = q.top();
q.pop();
if(vis[u.id]) continue;
vis[u.id] = 1;
for(int i=head[u.id];~i;i=edge[i].next){
int v = edge[i].to;
if(!vis[v] && dcmp(dis2[v] - dis2[u.id] - edge[i].len * 1.0 / edge[i].speed) > 0){
dis2[v] = dis2[u.id] + edge[i].len * 1.0 / edge[i].speed;
q.push(st2{v, dis2[v]});
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int n, m;
cin >> n >> m;
memset(head, -1, sizeof head);
memset(dis, 0x3f, sizeof dis);
for(int i=0;i<m;i++){
int u, v, speed, len;
cin >> u >> v >> speed >> len;
Add_Edge(u, v, speed, len);
Add_Edge(v, u, speed, len);
}
int q;
dijkstra(1);
memset(vis, 0, sizeof vis);
for(int i=0;i<=n;i++) dis2[i] = INF2;
dijkstra2(1);
cin >> q;
while(q--){
int j;
char c;
cin >> j >> c;
if(c == 's'){
if(dis[j] == INF) cout << "IMPOSSIBLE\n";
else cout << dis[j] << ' ' << "km\n";
}else{
if(dcmp(dis2[j] - INF2) == 0) cout << "IMPOSSIBLE\n";
else cout << fixed << setprecision(8) << dis2[j] << ' ' << "h\n";
}
}
return 0;
}