CSU1808 地鐵

題目

題意 :
n個地鐵站,m條線路,地鐵站之間花費t時間,不屬於同一條線路的地鐵站需要“轉站”,即加上一個額外花費w(w爲線路代號的差值)。
求1到n的最短時間。
思路:
題意很清晰,就是一個最短路。與一般的不同的是多出來一個線路的概念,不同線路之間有花費。
一個站點可以屬於多個線路。那麼只需要將一個站點根據線路拆爲多個點,通過新的點形成的圖,相當於每一個點有一個flag,不同加上花費。那麼通過兩次加邊,一次是不同站點之間的cost,一次是同一站點同一站點不同線路的拆點之間的cost。
然後直接在這個圖上跑最短路就可以了
最後求n點的花費,需要遍歷n的所有拆點,找到花費最小的一個,即爲答案。

#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];
map<int,int>mp[maxn];

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\n",ans);
    }
    return 0;
}
發佈了68 篇原創文章 · 獲贊 23 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章