• CSU 1808 地铁


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

    最短路。

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

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

    如果没有想通为什么只记录到某节点最短路是错的,可以看看下面这组数据,答案是$8$,走第二条和第三条即可。
    $3$ $3$
    $1$ $2$ $1$ $2$
    $1$ $2$ $3$ $3$
    $2$ $3$ $3$ $5$
    #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;
    }
  • 相关阅读:
    java中数组的相关知识
    如何搭建Java开发环境(包括下载、安装和配置JDK)和Eclipse的安装
    java 8种基本数据类型的默认值及所占字节数
    C语言编写的简单的电话本管理系统
    C语言题库的上机题
    Spring Boot使用AJAX从数据库读取数据异步刷新前端表格
    JS,jQuery获取select标签中选中值的方法
    jQuery效果与扩展:左右滑动
    使用EasyUI创建分页对比效果
    一些关于链表操作的代码
  • 原文地址:https://www.cnblogs.com/zufezzt/p/5838107.html
Copyright © 2020-2023  润新知