CSU1808 地铁

来源:互联网 发布:10m网络一年多少钱 编辑:程序博客网 时间:2024/04/24 01:36

题目

题意 :
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;}
0 1
原创粉丝点击