1到每个点的最短时间,不仅与到相邻点的最短距离有关,而且与地铁的换乘有关.
如果用dp[ni][ci]保存数据(ni地铁站点,ci地铁班次)
dp[from][ci]=min(dp[from][ci],dp[to][ci2]+abs(ci-c i2)+cost[to][from]),内存使用不理想;
所以可以保存(从1出发,最后走过这条边的最短时间);
每条边建立时可以保存对应的c,t;再利用dijkstra的思想更新(从1出发,最后走过这条边的最短时间),终点为n的边对应的最小值即为答案;
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#define M 100005
#define inf 1000000005
using namespace std;
struct dd
{
int id;
long long dp;
friend bool operator <(dd a,dd b)
{
return a.dp>b.dp;
}
};
struct edge
{
int to;
int from;
int c;
int t;
int next;
}e[M*2];
int head[M],vis[M*2];
long long d[M*2];
int ans=0,n,m;
void addedge(int to,int from,int c,int t)
{
e[ans].to=to,e[ans].from=from,e[ans].c=c,e[ans].t=t,e[ans].next=head[to],head[to]=ans++;
e[ans].from=to,e[ans].to=from,e[ans].c=c,e[ans].t=t,e[ans].next=head[from],head[from]=ans++;
}
long long djk()
{
long long ans=inf;
priority_queue<dd> p;
for(int i=0;i<=m*2;i++)
{
d[i]=inf;vis[i]=0;
if(e[i].to==1)
{
d[i]=e[i].t;
p.push(dd{i,d[i]});
}
}
while(!p.empty())
{
dd t1=p.top();
p.pop();
int id=t1.id;
if(vis[id])
continue;
vis[id]=true;
if(e[id].from==n) ans=min(ans,t1.dp);
int s=e[id].from;
for(int i=head[s];i!=-1;i=e[i].next)
{
if(!vis[i]&&d[i]>d[id]+e[i].t+abs(e[id].c-e[i].c))
{
d[i]=d[id]+e[i].t+abs(e[id].c-e[i].c);
p.push(dd{i,d[i]});
}
}
}
return ans;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
ans=0;
for(int i=0;i<=n;i++)
head[i]=-1;
for(int i=0;i<m;i++)
{
int to,from,c,t;
scanf("%d%d%d%d",&to,&from,&c,&t);
addedge(to,from,c,t);
}
cout<<djk()<<endl;
}
return 0;
}