[最短路]xt 1141 Bus Transit
来源:互联网 发布:知网 社会经济数据库 编辑:程序博客网 时间:2024/04/28 11:36
/**[最短路]xt 1141 Bus Transit公交图上有一些线路,同一站点可能存在于不同线路上或在一线路上出现多次,公交线路的换乘需要一定的时间代价T求从起点到终点的最小时间(相同情况下选择最小换乘路线)题意很明显是最短路,跑一圈dijkstra即可,这要求图上每个点都不一样,如果把同名站点拆开,两两之间建立权为T的边肯定会TLE。仔细考虑,同名站点的换乘肯定是从最短到达进行换乘的,即dijkstra时若首次弹出某个站点,则一次更新所有同名的站点(带换乘方案的)。于是,每个站点有两个编号,一是输入中的顺序编号,二是所属于那个同名站点的集合,前者朴素dijkstra,后者转乘方案*/#include <stdio.h>#include <string.h>#include <string>#include <map>#include <vector>#include <iostream>#include <queue>#include <algorithm>using namespace std;#define N 100007#define INF 1000000000#define Pii pair<int,int>#define MK make_pairint id[N],vis[N],trans[N],d[N],dt[N];int cnt,k,n,t,w;string S,B,str;vector< Pii > g[N];vector<int > tpot[N];map<string,int > smp;void dij(){ int u,v,i,j; int s = smp[S],b = smp[B]; memset(vis,0,sizeof(vis)); for(i = 0; i < cnt; ++i) d[i] = INF; priority_queue<Pii,vector<Pii>,greater<Pii> > que; for(i = 0; i < tpot[s].size(); ++i) { u = tpot[s][i]; d[u] = dt[u] = 0; que.push(MK(0,u)); } while(!que.empty()) { u = que.top().second; k = id[u]; if(k == b) { printf("%d %d\n",d[u],dt[u]); return ; } que.pop(); if(vis[u]) continue; vis[u] = 1; for(i = 0; i < g[u].size(); ++i) { v = g[u][i].first; w = g[u][i].second; if(d[v] > d[u] + w) { d[v] = d[u] + w; dt[v] = dt[u]; que.push(MK(d[v],v)); } } if(trans[k] == 0) { trans[k] = 1; for(i = 0; i < tpot[k].size(); ++i) { v = tpot[k][i]; if(v == u) continue; if(d[v] > d[u] + t) { d[v] = d[u] + t; dt[v] = dt[u] + 1; que.push(MK(d[v],v)); } } } } puts("-1");}int main(){ int i,a; while(scanf("%d%d",&n,&t) != EOF) { cin >> S >> B; memset(trans,-1,sizeof(trans)); memset(g,0,sizeof(g)); memset(tpot,0,sizeof(tpot)); smp.clear(); cnt = 0; while(n--) { k = cnt + 1; scanf("%d",&a); for(i = 0; i < a; ++i) { cin >> str; if(smp.find(str) == smp.end()) smp[str] = smp.size(); else trans[smp[str]] = 0; id[cnt] = smp[str]; tpot[id[cnt]].push_back(cnt); ++cnt; } for(i = 1; i < a; ++i,++k) { scanf("%d",&w); g[k].push_back(MK(k-1,w)); g[k-1].push_back(MK(k,w)); } } dij(); } return 0;}