zoukankan      html  css  js  c++  java
  • 地铁(最短路)

    1808: 地铁

    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
    ",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 }
    View Code
  • 相关阅读:
    js最全的十种跨域解决方案
    最常用的~正则表达式相关js函数知识简洁分享【新手推荐】
    HTTP请求 响应状态码
    堆和栈的区别【以java为例潜入分析】
    练习110 编写一个将输入复制到输出的程序,并将其中的制表符替换成\t,把回退符替换成\b,把反斜杠替换成\\,这样可以将制表符和回退符以可见的方式显示出来
    练习111 你准备如何测试单词计数程序? 如果程序中存在某种错误,那么什么样的输入最可能发现这类错误?
    练习114 编写一个程序, 打印输入中各个字符出现频度的直方图。
    The C programming language Test
    进驻首日..感谢师父的教导
    练习112:编写一个程序,以每行一个单词的形式打印其输入。
  • 原文地址:https://www.cnblogs.com/haoabcd2010/p/7356183.html
Copyright © 2011-2022 走看看