Description
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
题意:每个边都有一个线路,在站点换线的代价是两线的差值的绝对值,问1-n最短路.
思路:我们把边看为点,但是如果一个点两边各有1e5个线路,是不可能建这么多边的,所以我们可以每次只对一个点建边(这里的点就是原图的边),建的边的目标就是原图中这条边所连得点的所连得边,然后每次从优先队列里取出最小的那个来,这样他就可以被标记了,以后再也不用走来这了,也就是说下次有点想往这建边我们完全可以不建,这样不就节省了大量空间了嘛!
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<cstring>
#include<string>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 1000000007
using namespace std;
typedef long long ll;
const int maxn = 1e6+500;
const double esp = 1e-7;
const int ff = 0x3f3f3f3f;
map<int,int>::iterator it;
struct node
{
int u;
int v;
ll w;
int ne;
int line;
}edge[maxn];
int n,m,len;
int vis[maxn];
int head[maxn];
ll dis[maxn];
void add(int u,int v,int line,ll w)
{
edge[len].u = u;
edge[len].v = v;
edge[len].w = w;
edge[len].line = line;
edge[len].ne = head[u];
head[u] = len++;
}
ll DJ()
{
priority_queue< pair<ll,int>, vector<pair<ll,int> >, greater<pair<ll,int> > > q;
for(int i = head[1];i!= -1;i = edge[i].ne)
{
dis[i] = edge[i].w;
q.push(make_pair(dis[i],i));
}
while(!q.empty())
{
pair<ll,int> it = q.top();
q.pop();
int now = it.second;
if(edge[now].v == n)
return dis[now];
if(vis[now]) continue;
vis[now] = 1;
for(int i = head[edge[now].v];i!= -1;i = edge[i].ne)
{
if(dis[i]> dis[now]+abs(edge[now].line - edge[i].line)+edge[i].w)
{
dis[i] = dis[now]+abs(edge[now].line - edge[i].line)+edge[i].w;
q.push(make_pair(dis[i],i));
}
}
}
return -1;
}
void init()
{
len = 0;
mem(vis,0);
mem(head,-1);
for(int i = 0;i< maxn;i++)
dis[i] = 1e16;
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
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);
}
printf("%lld\n",DJ());
}
return 0;
}