1808: 地铁
Time Limit: 5 Sec Memory Limit: 128 Mb Submitted: 1080 Solved: 255Description
Bobo 居住在大城市 ICPCCamp。
ICPCCamp 有 n 个地铁站,用 1,2,…,n 编号。 m 段双向的地铁线路连接 n 个地铁站,其中第 i 段地铁属于 c
i 号线,位于站 a
i,b
i 之间,往返均需要花费 t
i 分钟(即从 a
i 到 b
i 需要 t
i 分钟,从 b
i 到 a
i 也需要 t
i 分钟)。
众所周知,换乘线路很麻烦。如果乘坐第 i 段地铁来到地铁站 s,又乘坐第 j 段地铁离开地铁站 s,那么需要额外花费 |c
i-c
j | 分钟。注意,换乘只能在地铁站内进行。
Bobo 想知道从地铁站 1 到地铁站 n 所需要花费的最小时间。
Input
输入包含不超过 20 组数据。
每组数据的第一行包含两个整数 n,m (2≤n≤10
5,1≤m≤10
5).
接下来 m 行的第 i 行包含四个整数 a
i,b
i,c
i,t
i (1≤a
i,b
i,c
i≤n,1≤t
i≤10
9).
保证存在从地铁站 1 到 n 的地铁线路(不一定直达)。
Output
对于每组数据,输出一个整数表示要求的值。
Sample Input
3 3 1 2 1 1 2 3 2 1 1 3 1 1 3 3 1 2 1 1 2 3 2 1 1 3 1 10 3 2 1 2 1 1 2 3 1 1
Sample Output
1 3 2
Hint
Source
湖南省第十二届大学生计算机程序设计竞赛思路:
1、一道经典的题型(之前刷专题的时候竟然没有关注过这类题),从u到v有两个长度的限制.很明显我们的思路不能将点作为状态去Dp了,我们要以边去作为状态去Dp是最优的,设定dist【i】表示通过第i条边到达e【i】.to所用的最短路径长度。
那么我们此时的点数是2*m个(因为边是无向边)。
又因为这样去设定的话边的条数确定不了,所以我们用Dij+堆优化更稳妥一些。
2、那么我们直接以边作为点,然后跑最短路即可,注意数据范围。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
#define ll long long int
struct node
{
ll from,to,w,c,next;
}e[445000];
struct node2
{
ll u,len;
friend bool operator <(node2 a,node2 b)
{
return a.len>b.len;
}
}now,nex;
ll cont;
ll n,m;
ll vis[4050000];
ll head[150000];
ll dis[10050000];
void add(ll from,ll to,ll c,ll w)
{
e[cont].to=to;
e[cont].w=w;
e[cont].c=c;
e[cont].next=head[from];
head[from]=cont++;
}
void Dij_Heap()
{
memset(vis,0,sizeof(vis));
priority_queue<node2>s;
for(ll i=0;i<=cont+10;i++)dis[i]=0x3f3f3f3f;
for(ll i=head[1];i!=-1;i=e[i].next)
{
now.u=i;
now.len=e[i].w;
dis[i]=e[i].w;
s.push(now);
}
while(!s.empty())
{
now=s.top();
s.pop();
ll u=now.u;
if(vis[u]==1)continue;
vis[u]=1;
for(ll i=head[e[u].to];i!=-1;i=e[i].next)
{
ll v=i;
if(dis[v]>dis[u]+e[i].w+abs(e[i].c-e[u].c))
{
dis[v]=dis[u]+e[i].w+abs(e[i].c-e[u].c);
nex.u=v;
nex.len=dis[v];
s.push(nex);
}
}
}
ll ans=0x3f3f3f3f;
for(ll i=0;i<cont;i++)
{
if(e[i].to==n)
{
ans=min(ans,dis[i]);
}
}
printf("%lld\n",ans);
}
int main()
{
while(~scanf("%lld%lld",&n,&m))
{
cont=0;
memset(head,-1,sizeof(head));
for(ll i=0;i<m;i++)
{
ll x,y,c,w;
scanf("%lld%lld%lld%lld",&x,&y,&c,&w);
add(x,y,c,w);
add(y,x,c,w);
}
Dij_Heap();
}
}