CSU 1808 地铁

湖南省第十二届大学生计算机程序设计竞赛$F$题。

最短路。

如果只记录到某个节点的最短路,显然是错误的。这题的状态有两个量决定,即到了哪一个节点,最后一辆乘坐的是几号线。这个可以用$map$记录一下。

要注意的是:如果用$SPFA$,因为要标记某个状态是否在队列中,还需要额外开一个$map$,这样可能导致超时;用$dijkstra$$+$优先队列优化的话就可以通过。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-6;
void File()
{
    freopen("D:\\in.txt","r",stdin);
    freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
    char c = getchar(); x = 0;while(!isdigit(c)) c = getchar();
    while(isdigit(c)) { x = x * 10 + c - ‘0‘; c = getchar();  }
}

const LL INF=(LL)1e17;
const int maxn=200010;
struct Edge
{
    int u,v,c; LL t;
    int nx;
}e[maxn];
int h[maxn],sz;
int n,m;
LL ans[maxn];

void add(int u,int v,int c,LL t)
{
    e[sz].u=u; e[sz].v=v; e[sz].c=c; e[sz].t=t;
    e[sz].nx=h[u]; h[u]=sz++;
}

struct Node
{
    int p,id;
    LL dis;
    Node(int P,int ID,LL DIS) { dis=DIS, p=P, id=ID; }
    bool operator < (const Node &a) const {
        if(dis==a.dis&&p==a.p) return id>a.id;
        if(dis==a.dis) return p>a.p;
        return dis>a.dis;
    }
};

struct X
{
    int p,id;
    X (int P,int ID) { p=P, id=ID; }
    bool operator < (const X &a) const {
        if(p==a.p) return id>a.id;
        return p>a.p;
    }
};

LL ABS(LL a) { if(a>=0) return a; return -a; }

void dij()
{
    map<X,LL>f; priority_queue<Node>Q;
    Q.push(Node(1,0,0));
    for(int i=1;i<=n;i++) ans[i]=INF; ans[1]=0;

    while(!Q.empty())
    {
        Node top=Q.top(); Q.pop();
        ans[top.p]=min(ans[top.p],top.dis);
        if(top.dis>f[X(top.p,top.id)]) continue;

        for(int i=h[top.p];i!=-1;i=e[i].nx)
        {
            LL COST;
            if(top.p==1) COST=0;
            else COST=ABS((LL)e[i].c-(LL)top.id);

            LL pp=f[X(e[i].v,e[i].c)];
            if((pp==0&&e[i].v!=1)||top.dis+COST+e[i].t<pp)
            {
                f[X(e[i].v,e[i].c)]=top.dis+COST+e[i].t;
                Q.push(Node(e[i].v,e[i].c,top.dis+COST+e[i].t));
            }
        }
    }
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(h,-1,sizeof h); sz=0;
        for(int i=1;i<=m;i++)
        {
            int u,v,c; LL t;
            scanf("%d%d%d%lld",&u,&v,&c,&t);
            add(u,v,c,t); add(v,u,c,t);
        }
        dij();
        cout<<ans[n]<<endl;
    }
    return 0;
}
时间: 2024-12-11 10:50:32

CSU 1808 地铁的相关文章

【最短路】【STL】CSU 1808 地铁 (2016湖南省第十二届大学生计算机程序设计竞赛)

题目链接: http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1808 题目大意: N个点M条无向边(N,M<=105),每条边属于某一条地铁Ci(Ci<=109),每条边有一个耗时,如果乘Ci号线地铁到达一个节点换乘Cj号线地铁离开,还需要花费|Ci-Cj|时间. 求1到n的最小花费时间. 题目思路: [最短路][STL] d[u][Ci]表示从1到u,最后一条地铁是Ci号线的最小耗时.按照边做,每条边枚举上一个是从哪一条地铁坐过来的,更新答案

CSU 1808 - 地铁 - [最短路变形]

题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1808 Time limit: 5000 ms Memory limit: 131072 kB Bobo 居住在大城市 ICPCCamp. ICPCCamp 有 n 个地铁站,用 1,2,-,n 编号. m 段双向的地铁线路连接 n 个地铁站,其中第 i 段地铁属于 c i 号线,位于站 a i,b i 之间,往返均需要花费 t i 分钟(即从 a i 到 b i需要 t i 分钟,

1808: 地铁

1808: 地铁 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 693  Solved: 161[Submit][Status][Web Board] Description Bobo 居住在大城市 ICPCCamp. ICPCCamp 有 n 个地铁站,用 1,2,…,n 编号. m 段双向的地铁线路连接 n 个地铁站,其中第 i 段地铁属于 ci 号线,位于站 ai,bi 之间,往返均需要花费 ti 分钟(即从 ai 到 bi 需要 ti 分钟

CSU 1808:地铁(Dijkstra)

http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1808 题意:…… 思路:和之前的天梯赛的一题一样,但是简单点. 没办法直接用点去算.把边看成点去做,规定dis[i]为走完第i条边之后即达到edge[i].v这个点的时候需要的花费. 点数为2*m.如果用普通的Dijkstra和SPFA会超时,所以用优先队列优化的Dijkstra. 1 #include <bits/stdc++.h> 2 using namespace std; 3 #d

[CSUOJ1808] 地铁(dijkstra,堆,边最短路)

题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1808 题意:题面挺清楚啦,就是求一个最短路.只不过每个点之间的边有可能是不同线路的,要从一个线路换到另一个线路是需要花费时间的. 边有特殊的定义,那么就不以点为分析对象做最短路了.直接拿边,dis(i)表示从1到达第i条边的指向点为终点的最短距离,每次松弛找到的边的目的点是t的时候更新一下结果. 1 #include <algorithm> 2 #include <iostre

CSU 1804: 有向无环图(拓扑排序)

http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1804 题意:…… 思路:对于某条路径,在遍历到某个点的时候,之前遍历过的点都可以到达它,因此在这个时候对答案的贡献就是∑(a1 + a2 + a3 + ... + ai) * bv,其中a是之前遍历到的点,v是当前遍历的点. 这样想之后就很简单了.类似于前缀和,每次遍历到一个v点,就把a[u]加给a[v],然后像平时的拓扑排序做就行了. 1 #include <bits/stdc++.h>

CSU 1111: 三家人【有趣的思维题】

1111: 三家人 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 2241  Solved: 874 [Submit][Status][Web Board] Description 有三户人家共拥有一座花园,每户人家的太太均需帮忙整理花园.A 太太工作了5 天,B 太太则工作了4 天,才将花园整理完毕.C 太太因为正身怀六甲无法加入她们的行列,便出了90元.请问这笔钱如何分给A.B 二位太太较为恰当?A 应得多少元?90/(5+4)*5=$50

CSU 1112: 机器人的指令【模拟题】

1112: 机器人的指令 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 1858  Solved: 682 [Submit][Status][Web Board] Description 数轴原点有一个机器人.该机器人将执行一系列指令,你的任务是预测所有指令执行完毕之后它的位置. ·LEFT:往左移动一个单位 ·RIGHT: 往右移动一个单位 ·SAME AS i: 和第i 条执行相同的动作.输入保证i 是一个正整数,且不超过之前执行指令数 In

北京地铁和广州地铁之感想

在北京生活了八年,前年回到广州,日常出行就靠地铁公交这些公共交通工具.对比帝都和羊城的地铁,各有各的特点.帝都地铁历史更悠久,线路更多:由于北京道路一般是横平竖直,地铁站命名更规律,十字路口的东北出入口为A,然后按顺时针分布依次为ABCD.羊城地铁最早的一号线建于九十年代,其他比起帝都地铁更新更先进,建设之初就通达机场各大火车站,更便捷.换成也比北京地铁方便,一般上下楼梯就可以换乘,不像北京地铁要绕很远才能换乘. 就日常使用来说,相对而言帝都地铁细节设计实用性更高一些,更人性化.例如:1.帝都地