URAL 1205 By the Underground or by Foot?(SPFA)

本文介绍了一个关于城市中寻找最快路线的问题,并通过SPFA算法解决。问题设定为从A点到B点,可通过步行或乘坐地铁的方式进行,且考虑了地铁站点之间的连接及其速度优势。文章提供了一段完整的C++代码实现。

By the Underground or by Foot?

Time limit: 1.0 second
Memory limit: 64 MB
Imagine yourself in a big city. You want to get from point A to point B. To do that you may move by foot or use the underground. Moving by the underground is faster but you may enter and exit it only at the stations. To save your time you decided to write a program to find the fastest route.

Input

The first line contains two floating point numbers. First of them is the speed of traveling by foot. The second one is the speed of traveling by the underground. The second speed is always greater than the first one.
Then description of the underground follows. It starts with an integer number N in the first line. It is the number of the underground stations. You may assume that N is not greater than 200. The following N lines contain two floating point numbers each (i-th line contains the coordinates of i-th station). Then the description of the connections between stations follows. Each connection is determined by the pair of integers, i.e. by the numbers of connected stations. The list of connections is terminates with a pair of zeroes. We assume that all the connections are straight. So the time we need to travel between stations is equal to the distance between stations divided by the speed of traveling by the underground.
It should be mentioned also that entering and exiting the underground and changing trains are possible at the stations only and takes no time.
At last the coordinates of the points A and B are given, tha pair of coordinates in a line.

Output

The first line should contain the minimal time needed to get from the point A to the point B. Time should be given with the precision of 10−6. The second line describes the use of the underground while traveling. It starts with the number of visited stations with tha following list of visited stations in the order they should be visited.

Sample

inputoutput
1 100
4
0 0
1 0
9 0
9 9
1 2
1 3
2 4
0 0
10 10
10 0
2.6346295
4 4 2 1 3
Problem Author: Alexander Klepinin
【分析】最短路,SPFA。
 
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <time.h>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#define inf 0x3f3f3f3f
#define mod 10000
typedef long long ll;
using namespace std;
const int N=205;
const int M=100005;
int n,m,k=0;
double a,b;
int vis[N],pre[N];
double w[N][N],d[N];
char str[20];
bool flag=false;
struct man{
    double x,y;
}point[N];
void spfa()
{
    d[0]=0;
    vis[0]=1;
    queue<int>q;
    q.push(0);
    while(!q.empty()){
        int t=q.front();q.pop();
        vis[t]=0;
        for(int i=0;i<=n+1;i++){
            if(d[i]>d[t]+w[t][i]){
                d[i]=d[t]+w[t][i];
                pre[i]=t;
                if(!vis[i])q.push(i),vis[i]=1;
            }
        }
    }
}
int main() {
    for(int i=0;i<N;i++){
        d[i]=10000000;
        for(int j=0;j<N;j++){
            w[i][j]=10000000;
        }
    }
    scanf("%lf%lf",&a,&b);
    scanf("%d",&n);
    int u,v;

    for(int i=1;i<=n;i++){
        scanf("%lf%lf",&point[i].x,&point[i].y);
    }
    while(~scanf("%d%d",&u,&v)&&u&&v){
        double s=sqrt((point[u].x-point[v].x)*(point[u].x-point[v].x)+(point[u].y-point[v].y)*(point[u].y-point[v].y));
        w[u][v]=w[v][u]=s/b;
    }
    scanf("%lf%lf%lf%lf",&point[0].x,&point[0].y,&point[n+1].x,&point[n+1].y);
    for(int i=0;i<=n+1;i++){
        for(int j=i+1;j<=n+1;j++){
            if(w[i][j]<10000000)continue;
            double s=sqrt((point[i].x-point[j].x)*(point[i].x-point[j].x)+(point[i].y-point[j].y)*(point[i].y-point[j].y));
            w[i][j]=w[i][j]=s/a;
        }
    }
    spfa();
    printf("%.7lf\n",d[n+1]);
    stack<int>p;
    for(int i=n+1;pre[i];i=pre[i]){
        p.push(pre[i]);
    }
    printf("%d",p.size());
    while(!p.empty())printf(" %d",p.top()),p.pop();
    return 0;
}
View Code

转载于:https://www.cnblogs.com/jianrenfang/p/5875457.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值