Dijkstra
最后一个测试点超时
(突然想到或许可以用BFS记录第一次到达终点时的路径,如果两条路径均在同一层到达终点,则选换乘最少的那条,心态写炸了,过几天回来试试这个方法)
#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
#include <climits>
using namespace std;
struct Road{
int station;
int line;
Road(int s,int l){
station = s;
line = l;
}
};
struct Result{
int line;
int start;
int end;
Result(int l,int e){
line = l;
end = e;
}
};
vector<Road> G[10010];
unordered_set<int> S;
int d[10010];
int pre[10010];
int transfer[10010];
bool vis[10010];
void Dijkstra(int s){
fill(d,d + 10010,INT_MAX);
fill(pre,pre + 10010,-1);
fill(transfer,transfer + 10010,INT_MAX);
fill(vis,vis + 10010,false);
d[s] = 0;transfer[s] = 0;pre[s] = s;
int n = S.size();
for(int i = 0;i < n;i++){
int u = -1,MIN = INT_MAX,minTrans = INT_MAX;
unordered_set<int>::iterator it = S.begin();
while(it != S.end()){
if(vis[*it] == false && (d[*it] < MIN || (d[*it] == MIN && transfer[*it] < minTrans))){
u = *it;
MIN = d[*it];
minTrans = transfer[*it];
}
it++;
}
if(u == -1)
return;
vis[u] = true;
for(int j = 0;j < G[u].size();j++){
int v = G[u][j].station;
int t;
if(u != s){
int temp;
for(temp = 0;temp < G[u].size();temp++){
if(G[u][temp].station == pre[u])
break;
}
t = G[u][j].line == G[u][temp].line ? 0 : 1;
}
else
t = 0;
if(vis[v] == false && (d[u] + 1 < d[v] || (d[u] + 1 == d[v] && transfer[u] + t < transfer[v]))){
d[v] = d[u] + 1;
transfer[v] = transfer[u] + t;
pre[v] = u;
}
}
}
}
int main(){
int n;
scanf("%d",&n);
for(int i = 1;i <= n;i++){
int m;
scanf("%d",&m);
int u,v;
scanf("%d",&u);
S.insert(u);
for(int j = 1;j < m;j++){
scanf("%d",&v);
Road r(v,i);
G[u].push_back(r);
r.station = u;
G[v].push_back(r);
u = v;
S.insert(v);
}
}
int k;
scanf("%d",&k);
for(int i = 0;i < k;i++){
int cnt = 0;
int source,destination;
scanf("%d %d",&source,&destination);
Dijkstra(source);
int d = destination;
vector<Result> res;
int temp;
for(temp = 0;temp < G[d].size();temp++){
if(G[d][temp].station == pre[d])
break;
}
int curLine = G[d][temp].line;
res.push_back(Result(curLine,d));
int switchTime = 0; // 换乘次数
while(pre[d] != d){
cnt++;
for(temp = 0;temp < G[d].size();temp++){
if(G[d][temp].station == pre[d])
break;
}
if(G[d][temp].line != curLine){ // 换乘,d是中转站
res[switchTime].start = d;
curLine = G[d][temp].line;
res.push_back(Result(curLine,d));
switchTime++;
}
d = pre[d];
res[switchTime].start = source;
}
printf("%d\n",cnt);
while(switchTime >= 0){
printf("Take Line#%d from %04d to %04d.\n",res[switchTime].line,res[switchTime].start,res[switchTime].end);
switchTime--;
}
}
system("pause");
return 0;
}