地铁(最短路)
Time Limit: 5 Sec Memory Limit: 128 Mb Submitted: 1466 Solved: 350
Description
Bobo 居住在大城市 ICPCCamp。
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 所需要花费的最小时间。
Input
输入包含不超过 20 组数据。
每组数据的第一行包含两个整数 n,m (2≤n≤105,1≤m≤105).
接下来 m 行的第 i 行包含四个整数 ai,bi,ci,ti (1≤ai,bi,ci≤n,1≤ti≤109).
保证存在从地铁站 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
// 貌似是最短路模板题,但是,用点来跑最短路显然是错的,因为,每次松弛都不能记录是由哪条线路松弛的。为了知道是怎么松弛的。
我们可以用边来跑最短路,dis[i] 表示由 i 边到达 edge[i].to 点的最短路,这样可以愉快的松弛所有边了!有的大牛用了拆点的方法,就是把一个点分成多个线路的点,建图都比较难想,还是比较麻烦
1 # include <cstdio> 2 # include <cstring> 3 # include <cstdlib> 4 # include <iostream> 5 # include <vector> 6 # include <queue> 7 # include <stack> 8 # include <map> 9 # include <bitset> 10 # include <sstream> 11 # include <set> 12 # include <cmath> 13 # include <algorithm> 14 #pragma comment(linker,"/STACK:102400000,102400000") 15 using namespace std; 16 #define LL long long 17 #define lowbit(x) ((x)&(-x)) 18 #define PI acos(-1.0) 19 #define INF 0x3f3f3f3f3f3f3f3f 20 #define eps 1e-8 21 #define MOD 1000000007 22 23 inline int scan() { 24 int x=0,f=1; char ch=getchar(); 25 while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();} 26 while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} 27 return x*f; 28 } 29 inline void Out(int a) { 30 if(a<0) {putchar('-'); a=-a;} 31 if(a>=10) Out(a/10); 32 putchar(a%10+'0'); 33 } 34 #define MX 100005 35 /**************************/ 36 struct Edge 37 { 38 int to,c; 39 int dis; 40 int nex; 41 }edge[MX*2]; 42 struct Node 43 { 44 LL dis; 45 int dex; 46 bool operator < (const Node & x)const{return dis>x.dis;} 47 }; 48 int n,m; 49 int rm; 50 int hlist[MX]; 51 LL dis[MX*2]; 52 bool vis[MX*2]; 53 void add_edge(int u,int v,int c,int d) 54 { 55 edge[rm] = (Edge){v,c,d,hlist[u]}; 56 hlist[u] = rm++; 57 edge[rm] = (Edge){u,c,d,hlist[v]}; 58 hlist[v] = rm++; 59 } 60 61 void Dij(int s,int t) 62 { 63 memset(vis,0,sizeof(vis)); 64 memset(dis,0x3f,sizeof(dis)); 65 LL ans = INF; 66 priority_queue<Node> Q; 67 for (int i=hlist[1];i!=-1;i=edge[i].nex) 68 { 69 dis[i] = edge[i].dis; 70 Q.push((Node){edge[i].dis,i}); 71 } 72 while (!Q.empty()) 73 { 74 Node now = Q.top(); Q.pop(); 75 int dx = now.dex; 76 int u = edge[dx].to; 77 if (vis[dx]) continue; 78 vis[dx]=1; 79 if (u==t) ans = min(ans,dis[dx]); 80 for (int i=hlist[u];i!=-1;i=edge[i].nex) 81 { 82 if (!vis[i]&&dis[i]>dis[dx]+abs(edge[i].c-edge[dx].c)+edge[i].dis) 83 { 84 dis[i] = dis[dx]+abs(edge[i].c-edge[dx].c)+edge[i].dis; 85 Q.push((Node){dis[i],i}); 86 } 87 } 88 } 89 printf("%lld\n",ans); 90 } 91 92 int main() 93 { 94 while (scanf("%d%d",&n,&m)!=EOF) 95 { 96 rm=0; 97 memset(hlist,-1,sizeof(hlist)); 98 for (int i=1;i<=m;i++) 99 { 100 int u,v,c,d; 101 u=scan(); v=scan(); 102 c=scan(); d=scan(); 103 add_edge(u,v,c,d); 104 } 105 Dij(1,n); 106 } 107 return 0; 108 }