HN0I2000最优乘车 (最短路变形)

HN0I2000最优乘车 (最短路变形)

【试题】为了简化城市公共汽车收费系统,某城市决定对大部分的公共汽车都采用一票制,但由于某些公共汽车所经过的停车站太多和路途太长,就采用两票或多票制。经过这种票制改革后,人们坐公共汽车从一个站到另一个站时,就不得不选择一个好的乘车方案,以使他们的乘车费用最低。

为了方便于求出最佳的乘车方案,我们假设:

l  采用一票制的公共汽车,无论从哪个站上车到那个站下车,乘该公共汽车的费用为1(费用单位)。

l  采用多票制的公共汽车,将设立某些站为关键站;那么,如果某人乘该路公共汽车从A站到B站时,不经过任何关键站的乘车费用为1,而经过K个关键站的乘车费用为K+1;所谓经过关键站是指:乘该路公共汽车时,该关键站是其途中的一个站,但它不是上车站也不是下车站;例如,某路公共汽车经过1,2,3,4,*5,6,7,8,9;其中5是关键站,那么,从5站上车到9站下车或从2站上车到5站下车的费用为1,而从4站上车到6站下车的费用将是2。

l  所有公共汽车都是双向行驶的,也即如果公共汽车经过的站点有A和B,那么,你可以乘该公共汽车从A到B或从B到A。

你的任务就是:对于输入文件中给出的公共汽车各停车站,和某乘客的起点站A和终点站B,请你编程为乘客求出最佳的乘车方案,使得他的乘车费用最少。

输入:第1行为N、R、A和B,其中N为城市公共汽车停车站的总个数,这些停车站被统一编号为1、2、……、N;R为公共汽车总路数。A为起点站的编号,B为终点站的编号。(1≤N≤1000,1≤R≤300,每路公共汽车的最多站点数为20)。数据之间用空格分开。

第2行到R+1行的每一行为一路公共汽车经过的停车站编号,停车站编号的排列顺序是该路公共汽车按一个方向行车顺序依次经过的停车站,如为关键停车站,则其编号的前面有一个*。每行数据之间用空格分开。

输出:从A站到B站所需的最少费用。如果不能乘这些公共汽车从A到B,输出-1。

输入输出示例:

INPUT4.TXT

12 4 1 12

1 2 3 *4 5 6 7

1 2 3 8

8 4 5 9

7 6 5 *9 10 11 12

OUTPUT4.TXT

3

解题报告

好稀有的题目,在网上根本找不到的说。

很典型的最短路。对于每一条公交线路,我们让其中的每一个站点互相建边,使其权值为票价,注意边界问题,起点与终点为关键站不计入票价中。

用堆优dijkstra即可。

#include<bits/stdc++.h>
#define Pair pair<int,int>
#define MAXN 1000+10
#define MAXM 600000+1
using namespace std;
int n,m,num,head[MAXN],s,t,dis[MAXN],v[MAXM];
int pre[MAXN];

int read(int &k)
{
    int in=0,j=0;char c;
    c=getchar();
    for(;c>‘9‘||c<‘0‘;c=getchar())
    {
        if(c==‘\n‘) return 0;
        if(c==‘*‘) j=1;
    }
    for(;c<=‘9‘&&c>=‘0‘;c=getchar()) in=in*10+c-‘0‘;
    k=in;
    if(j) return 2;
    return 1;
}

struct Edge{
    int dis,next,to,exi,from;
}edge[MAXM];

void add(int from,int to,int dis)
{
    edge[++num].next=head[from];
    edge[num].to=to;
    edge[num].dis=dis;
    edge[num].from=from;
    head[from]=num;
    edge[num].exi=1;
}
void dij()
{
    memset(dis,0,sizeof(dis));
    memset(v,0,sizeof(v));
    priority_queue<Pair,vector<Pair>,greater<Pair> > h;
    for(int i=1;i<=n;i++) dis[i]=2147483647;
    dis[s]=0;
    h.push(Pair(dis[s],s));
    while(h.size()>0)
    {
        int k=h.top().second;h.pop();
        if(v[k]) continue;
        v[k]=1;
        for(int i=head[k];i;i=edge[i].next)
        if(dis[k]+edge[i].dis<dis[edge[i].to]&&edge[i].exi==1)
        {
            dis[edge[i].to]=dis[k]+edge[i].dis;
            h.push(Pair(dis[edge[i].to],edge[i].to));
            pre[edge[i].to]=edge[i].from;
        }
    }
}

int main()
{
    freopen("bus.in","r",stdin);
    freopen("bus.out","w",stdout);

    scanf("%d%d%d%d\n",&n,&m,&s,&t);
    for(int i=1;i<=m;i++)
    {
        int x,o,np=0;int p[MAXN][3],k=1;
        while(1)
        {
            o=read(x);if(o==0) break;
            else if(o==2) p[++np][0]=x,p[np][1]=k,k++,p[np][2]=k;
            else p[++np][0]=x,p[np][1]=p[np][2]=k;
        }
        for(int i=1;i<=np;i++)
        {
            for(int j=1+i;j<=np;j++)
            {

                int money=min( min(abs(p[i][1]-p[j][1]),abs(p[i][2]-p[j][2]))
                ,min(abs(p[i][1]-p[j][2]),abs(p[i][2]-p[j][1])));
                add(p[i][0],p[j][0],money+1);
                add(p[j][0],p[i][0],money+1);

            }
        }
    }

    dij();

    if(dis[t]>=2147483647) printf("-1\n");
    else printf("%d\n",dis[t]);
    return 0;
}
时间: 2024-12-28 00:25:42

HN0I2000最优乘车 (最短路变形)的相关文章

[最短路]1722 最优乘车

题目描述 Description H城是一个旅游胜地,每年都有成千上万的人前来观光.为方便游客,巴士公司在各个旅游景点及宾馆,饭店等地都设置了巴士站并开通了一些单程巴上线路.每条单程巴士线路从某个巴士站出发,依次途经若干个巴士站,最终到达终点巴士站. 一名旅客最近到H城旅游,他很想去S公园游玩,但如果从他所在的饭店没有一路巴士可以直接到达S公园,则他可能要先乘某一路巴士坐几站,再下来换乘同一站台的另一路巴士, 这样换乘几次后到达S公园. 现在用整数1,2,…N 给H城的所有的巴士站编号,约定这名

最优乘车

最优乘车 Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other) Total Submission(s) : 18   Accepted Submission(s) : 6 Problem Description H城是一个旅游胜地,每年都有成千上万的人前来观光.为方便游客,巴士公司在各个旅游景点及宾馆.饭店等地都设置了巴士站并开通了一些单程巴士线路.每条单程巴士线路从某个巴士站出发,依次途

【NOI97】最优乘车

Description H城是一个旅游胜地,每年都有成千上万的人前来观光.为方便游客,巴士公司在各个旅游景点及宾馆,饭店等地都设置了巴士站并开通了一些单程巴上线路.每条单程巴士线路从某个巴士站出发,依次途经若干个巴士站,最终到达终点巴士站. 一名旅客最近到H城旅游,他很想去S公园游玩,但如果从他所在的饭店没有一路巴士可以直接到达S公园,则他可能要先乘某一路巴士坐几站,再下来换乘同一站台的另一路巴士, 这样换乘几次后到达S公园. 现在用整数1,2,…N 给H城的所有的巴士站编号,约定这名旅客所在饭

URAL 1934 Black Spot --- 简单最短路变形

边权为1,在维护最短路的同时维护p值最小,我直接存的(1-p),即不遇见的概率,要使得这个值最大. #include <iostream> #include <cstdlib> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #includ

UESTC 915 方老师的分身II --最短路变形

即求从起点到终点至少走K条路的最短路径. 用两个变量来维护一个点的dis,u和e,u为当前点的编号,e为已经走过多少条边,w[u][e]表示到当前点,走过e条边的最短路径长度,因为是至少K条边,所以大于K条边的当做K条边来处理就好了.求最短路的三个算法都可以做,我这里用的是SPFA,比较简洁. 代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #incl

zoj 1655 Transport Goods (最短路变形)

Transport Goods Time Limit: 2 Seconds      Memory Limit: 65536 KB The HERO country is attacked by other country. The intruder is attacking the capital so other cities must send supports to the capital. There are some roads between the cities and the

noi 1997 最优乘车

H城是一个旅游胜地,每年都有成千上万的人前来观光.为方便游客,巴士公司在各个旅游景点及宾馆,饭店等地都设置了巴士站并开通了一些单程巴上线路.每条单程巴士线路从某个巴士站出发,依次途经若干个巴士站,最终到达终点巴士站. 一名旅客最近到H城旅游,他很想去S公园游玩,但如果从他所在的饭店没有一路已士可以直接到达S公园,则他可能要先乘某一路巴士坐几站,再下来换乘同一站台的另一路巴士, 这样换乘几次后到达S公园. 现在用整数1,2,…N 给H城的所有的巴士站编号,约定这名旅客所在饭店的巴士站编号为1…S公

zoj1655 最短路变形

题意:HERO过的首都需要货物,需要从其他的城市吧货物送到首都,每条道路都会需要消耗一定比例的货物,问最多能送多少货物到首都. 思路:如果每个点的比例是1,到达首都的比例就是经过的路径的(1-消耗比)的乘积,反正是无向的,所以可以反过来推,首都的货物比是1,而到达每座 城市的货物就是所经过的路径(1-消耗比)的乘积,则由此可见,我们可以求首都到任意城市的最大比值:最后把每个点的最大比值乘以每个点的货物加起来 即是结果. #include<stdio.h> #include<string.

POJ 1797 Heavy Transportation (最短路变形)

Heavy Transportation Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 20364   Accepted: 5401 Description Background Hugo Heavy is happy. After the breakdown of the Cargolifter project he can now expand business. But he needs a clever man