题意:
给你n个站点,m条线路(n,m<=1e5),每条线路(边)有一个时间,代表乘坐这条线路花费的时间,有一个线路号(1-n),如果你换乘了,那么,消耗的时间就多了abs(pre_c - now_c),问你从站点1到站点n,至少需要多少时间。
题解:
因为这个换乘的性质导致了他不能用点来贪心,也就没有办法使用dijkstra,下面的样例可以说明。
但是用边来贪心刚好满足性质,我们设d[i]代表从i点出发经过了第i条边的最小值,这样就符合了贪心的原理,我们就可以根据dijkstra求出所有连接终点的所有边的最小值,在其中取最小的即可。
#include <bits/stdc++.h>
#define ll long long
#define pi pair<ll,int>
#define mk make_pair
using namespace std;
const int maxn = 1e5+10;
const ll inf = 1e18;
int cnt;
int head[maxn];
struct Edge {
int next,v,c,t;
}G[maxn * 2];
void addA(int u,int v,int c,int t) {
G[cnt].v = v;
G[cnt].c = c;
G[cnt].t = t;
G[cnt].next = head[u];
head[u] = cnt++;
}
ll d[maxn*2];
bool vis[maxn*2];
void dij(int n,int m) {
priority_queue<pi>q;
for(int i=0;i<=2*m+2;i++)d[i] = inf,vis[i] = false;
for(int i=head[1];~i;i=G[i].next) {
int v = G[i].v;
int t = G[i].t;
d[i] = t;
q.push(mk(-d[i],i));
}
ll ans = inf;
while(!q.empty()) {
int u = q.top().second;
q.pop();
if(G[u].v == n) {
ans = min(ans , d[u]);
}
if(vis[u])continue;
vis[u] = true;
for(int i=head[G[u].v];~i;i=G[i].next) {
int v = G[i].v;
if(d[i] > d[u] + G[i].t + abs(G[i].c - G[u].c)) {
d[i] = d[u] + G[i].t + abs(G[i].c - G[u].c);
q.push(mk(-d[i],i));
}
}
}
printf("%lld\n",ans);
}
int main() {
int n,m;
while(~scanf("%d%d",&n,&m)) {
cnt = 0;
for(int i=0;i<=n;i++)head[i] = -1;
for(int i=1;i<=m;i++) {
int u,v,c,t;
scanf("%d%d%d%d",&u,&v,&c,&t);
addA(u,v,c,t);
addA(v,u,c,t);
}
dij(n,m);
}
}