zoukankan      html  css  js  c++  java
  • CSU 1808 地铁

    题意:

      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 所需要花费的最小时间。

    分析:

      很明显的最短路,但是有两个做法.

      一是按每个站点有几个地铁经过然后拆为多个点。然后两次添加边,第一次是添加不同站点之间的花费,第二次是是相同站点不同地铁线路的话费。

      二是把边当做状态dist[i]iedge[i].v费,2m 

    spfaTLEdijkstra+heap

    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

    方法一:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<map>
    #include<queue>
    #include<algorithm>
    using namespace std;
    
    const int maxn =255555;
    const int INF = 0x3f3f3f3f;
    
    int n,m;
    struct Edge{
        int to,next;
        int w;
    }edge[maxn*2];
    
    int head[maxn],tot;
    
    void init(){
        memset(head,-1,sizeof(head));
        tot=0;
    }
    void addedge(int u,int v,int w){
    
        edge[tot].to=v;
        edge[tot].next = head[u];
        edge[tot].w =w;
        head[u]=tot++;
    }
    
    vector<int>num[maxn];//存贮第i个站点跟哪几个地铁相连
    map<int,int>mp[maxn];//存贮第i个站点跟几个地铁相连
    
    int dis[maxn];
    int cnt;
    struct node{
        int now;
        int c;
        node(int  _now = 0,int _c=0):now(_now),c(_c){}
        bool operator <(const node &r)const
        {
            return c>r.c;
        }
    };
    void DJ(){
    
        priority_queue<node> que;
        while(!que.empty()) que.pop();
        for(int i=1;i<cnt;++i) dis[i]=INF;
        for(int i=0;i<num[1].size();++i){
            int st;
            st = mp[1][num[1][i]];
            dis[st]=0;
            que.push(node(st,0));
        }
        node temp;
        while(!que.empty()){
    
            temp = que.top();
            que.pop();
            int u = temp.now;
            int cost = temp.c;
            if(cost>dis[u])
            continue;
    
            for(int i=head[u];~i;i=edge[i].next){
    
                int v = edge[i].to;
                int w = edge[i].w;
                if(dis[v]>cost+w){
                    dis[v]= cost + w;
                    que.push(node(v,dis[v]));
                }
            }
        }
    }
    
    int main(){
    
        int u,v,w,x;
        while(scanf("%d%d",&n,&m)!=EOF){
    
            init();
            cnt=1;
            for(int i=1;i<=n;i++){
                num[i].clear();
                mp[i].clear();
            }
            for(int i=0;i<m;++i){
                scanf("%d%d%d%d",&u,&v,&x,&w);
                if(!mp[u][x]){
                    mp[u][x]=cnt++;
                    num[u].push_back(x);
                }
                u=mp[u][x];
                if(!mp[v][x]){
                    mp[v][x]=cnt++;
                    num[v].push_back(x);
                }
                v=mp[v][x];
                addedge(u,v,w);
                addedge(v,u,w);
            }
            for(int i=1;i<=n;i++){
                sort(num[i].begin(),num[i].end());
                for(int j=0;j<num[i].size()-1;++j){
    
                    u=mp[i][num[i][j]];
                    v=mp[i][num[i][j+1]];
    
                    w=num[i][j+1]-num[i][j]; //同一站点不同线路的拆点之间的差值
                    addedge(u,v,w);
                    addedge(v,u,w);
    
                }
            }
            DJ();
            int ans=INF;
            for(int i=0;i<num[n].size();i++){
                u=mp[n][num[n][i]];
                ans=min(ans,dis[u]);
    
            }
            printf("%d
    ",ans);
        }
        return 0;
    }

    方法二:

    #include <map>
    #include <set>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <sstream>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    #define   MAX           100005
    #define   MAXN          1000005
    #define   LL            long long
    
    inline void RI(int &x) {
          char c;
          while((c=getchar())<'0' || c>'9');
          x=c-'0';
          while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
     }
    
    
    struct Edge{
        int v,next,num,c;
    }edge[MAX*2];
    
    struct Node{
        int id,val;
        bool operator<(const Node &a)const{
            return val>a.val;
        }
    }x;
    
    int head[MAX];
    LL dis[MAX*2];
    int vis[MAX*2];
    int tot;
    
    void add_edge(int a,int b,int c,int d){
        edge[tot]=(Edge){b,head[a],c,d};
        head[a]=tot++;
        edge[tot]=(Edge){a,head[b],c,d};
        head[b]=tot++;
    }
    
    LL dijkstra(int s,int t){
        priority_queue<Node> q;
        for(int i=0;i<tot;i++){
            dis[i]=1e18;
            vis[i]=0;
        }
        for(int i=head[s];i!=-1;i=edge[i].next){
            x=(Node){i,edge[i].c};
            dis[i]=edge[i].c;
            q.push(x);
        }
        LL ans=1e18;
        while(!q.empty()){
            x=q.top();
            q.pop();
            int p=x.id;
            if(vis[p]) continue;
            vis[p]=1;
            int u=edge[p].v;
            if(u==t) ans=min(ans,dis[p]);
            for(int i=head[u];i!=-1;i=edge[i].next){
                int v=edge[i].v;
                if(!vis[i]&&dis[i]>dis[p]+edge[i].c+abs(edge[i].num-edge[p].num)){
                    dis[i]=dis[p]+edge[i].c+abs(edge[i].num-edge[p].num);
                    q.push((Node){i,dis[i]});
                }
            }
        }
        return ans;
    }
    int main() {
        int n,m;
        while(cin>>n>>m){
            tot=0;
            for(int i=1;i<=n;i++) head[i]=-1;
            for(int i=0;i<m;i++){
                int a,b,c,d;
                RI(a);RI(b);RI(c);RI(d);
                add_edge(a,b,c,d);
            }
            cout<<dijkstra(1,n)<<endl;
        }
        return 0;
    }

    dis[i]iedge[i].v 
    2m 
     
    spfaTLEdijkstra+heap

  • 相关阅读:
    双循环建表____1911年 为 辛亥年
    技巧方法
    sscanf
    02-02环境准备-pyenv与virtualenv以及venv方案对比
    02-01环境准备-virtualenv和venv
    02-01环境准备-pyenv
    【转】解决weblogic启动慢和创建域慢的方法
    chrome新版打开新标签页自动打开谷歌主页
    centos6分辨率设置
    12-openldap使用AD密码
  • 原文地址:https://www.cnblogs.com/137033036-wjl/p/5933500.html
Copyright © 2011-2022 走看看