题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=1808

题意:ICPCCamp 有 n 个地铁站,用 1,2,…,n 编号。 m 段双向的地铁线路连接 n 个地铁站,其中第 i 段地铁属于 ci 号

线,位于站 ai,bi 之间,往返均需要花费 ti 分钟(即从 ai 到 bi 需要 ti 分钟,从 bi 到 ai 也需要 ti 分钟)。

众所周知,换乘线路很麻烦。如果乘坐第 i 段地铁来到地铁站 s,又乘坐第 j 段地铁离开地铁站 s,那么需要额外花费 |ci-

cj | 分钟。注意,换乘只能在地铁站内进行。

Bobo 想知道从地铁站 1 到地铁站 n 所需要花费的最小时间。

解法:

这题如果把点当作状态的话有些不妥

其实这题因为有了额外花费这个条件,应该把边当作状态

dis[i]表示走过i这条边打到edge[i].v的最少花费

这样的话就2∗m条边

把边看作点来做最短路,但是这题的边数未知

所以spfa会TLE,所以要用dijkstra+heap

在写的过程中,发现了之前一个没注意的问题,pair

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int>pii;
#define mp(x,y) make_pair(x,y)
const int maxn = 500010;
int head[maxn], edgecnt;
void init(){
    memset(head, -1, sizeof(head));
    edgecnt=0;
}
struct edge{
    int v,next,num,c;
}E[maxn*2];
void add(int u, int v, int num, int c){
    E[edgecnt].v=v,E[edgecnt].next=head[u],E[edgecnt].num=num,E[edgecnt].c=c;
    head[u]=edgecnt++;
}
LL dis[maxn];//经过第i条边,到达E[i].v的最小花费
bool vis[maxn];

LL Dij(int s, int t){
    priority_queue<pii,vector<pii>,greater<pii> >q;
    //pair<int,LL> 边和距离值
    for(int i=0; i<edgecnt; i++) dis[i]=1e18, vis[i]=0;
    for(int i=head[s]; ~i; i=E[i].next){
        dis[i]=E[i].c;
        q.push(mp(E[i].c,i));
    }
    LL ans=1e18;
    while(!q.empty()){
        pii x=q.top(); q.pop();
        int p = x.second;
        if(vis[p]) continue;
        vis[p]=1;
        int u=E[p].v;
        if(u==t){
            ans = min(ans, dis[p]);
        }
        for(int i=head[u]; ~i; i=E[i].next){
            if(!vis[i]&&dis[i]>dis[p]+E[i].c+abs(E[i].num-E[p].num)){
                dis[i]=dis[p]+E[i].c+abs(E[i].num-E[p].num);
                q.push(mp(dis[i],i));
            }
        }
    }
    return ans;
}

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        init();
        for(int i=1; i<=m; i++){
            int a,b,c,t;
            scanf("%d%d%d%d",&a,&b,&c,&t);
            add(a,b,c,t);
            add(b,a,c,t);
        }
        LL ans=Dij(1,n);
        printf("%lld\n", ans);
    }
    return 0;
}