題意 :
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;
}