这一题意根据点之间的距离和时间,求某两点之间的距离最短路径和时间最短路径。
距离最短路径有相同,输出时间最短的。时间最短路径有相同,输出经过的节点最少的。
按指定的格式输出。
这一题用djs最短路径,一开始使用了dfs递归写法,但是由于函数递归的效率低下,导致最后一点超时。然后想改成循环的写法,看了一下自己以前关于最短路径的循环的代码,改了半天,发现没有通过,才发现自己用错了,用成了队列。dfs应该使用栈, 改完后,只有最后两个通过。后来在修改成别人的代码过程中,发现自己犯了一个低级错误,赋值赋错了,又回到自己的代码修改,在此过程中从别人那得到的理解对自己的代码进行优化,终于改出来。
根据每个点和相连接的点的距离,用数组把每个点的dist更新到最短的dist,然后将这个点标记为访问过。路径的保存是反向保存,后一节点指向前一个节点,这样可以保证更新了以后,后一个节点指向的前一个节点,一定是其最短距离相连的点。
(用时:7:51:03.51)
#include <bits/stdc++.h>
using namespace std;
#define INF 1000000
struct OnlineMap {
int vEnd;
int length;
int time;
};
void ShortestPath(int source,int destination,vector<OnlineMap> omp[],int n)
{
int vis[n]= {0};
stack<int> sta;
int dist[n];
int time[n];
int sPath[n];
int tPath[n];
for(int i=0; i<n; i++) {
dist[i] = INF;
time[i] = INF;
sPath[i] =INF;
tPath[i] =INF;
}
for(int i=0; i<omp[source].size(); i++) {
//到这一点的最短距离
dist[omp[source][i].vEnd] = omp[source][i].length;
//到这一点的时间
time[omp[source][i].vEnd] = omp[source][i].time;
sPath[omp[source][i].vEnd] =source;
tPath[omp[source][i].vEnd] =source;
}
dist[source] = 0;
time[source] = 0;
sta.push(source);
while(!sta.empty()) {
int index = sta.top();
sta.pop();
if(index!=destination) {
vis[index] = 1;
for(int i=0; i<omp[index].size(); i++) {
//无论有没有访问过,都要检测其dist
if(dist[index] + omp[index][i].length< dist[ omp[index][i].vEnd]) {
dist[omp[index][i].vEnd] = dist[index] + omp[index][i].length;
time[omp[index][i].vEnd] = time[index] + omp[index][i].time;
sPath[omp[index][i].vEnd] = index;
} else if(dist[index] + omp[index][i].length == dist[ omp[index][i].vEnd]) {
if( time[index] + omp[index][i].time < time[omp[index][i].vEnd]) {
time[omp[index][i].vEnd] = time[index] + omp[index][i].time;
sPath[omp[index][i].vEnd] = index;
}
}
if(!vis[omp[index][i].vEnd]) {
sta.push(omp[index][i].vEnd);
}
}
}
}
vector<int> sP;
int t = destination;
while(t!=source) {
sP.push_back(t);
t=sPath[t];
}
sP.push_back(source);
int distNum[n]= {0};
for(int i=0; i<n; i++) {
distNum[i] = INF;
vis[i] = 0;
}
time[source] = 0;
distNum[source] = 0;
sta.push(source);
while(!sta.empty()) {
int index = sta.top();
sta.pop();
if(index!=destination) {
vis[index] = 1;
for(int i=0; i<omp[index].size(); i++) {
if(time[index] + omp[index][i].time< time[omp[index][i].vEnd]) {
distNum[omp[index][i].vEnd] = distNum[index] + 1;
time[omp[index][i].vEnd] = time[index] + omp[index][i].time;
tPath[omp[index][i].vEnd] = index;
} else if(time[index] + omp[index][i].time==time[omp[index][i].vEnd]) {
if(distNum[index] + 1< distNum[omp[index][i].vEnd] ) {
distNum[omp[index][i].vEnd] = distNum[index] + 1;
tPath[omp[index][i].vEnd] = index;
}
}
if(! vis[omp[index][i].vEnd]) {
sta.push(omp[index][i].vEnd);
}
}
}
}
vector<int> timeP;
t = destination;
while(t!=source) {
timeP.push_back(t);
t=tPath[t];
}
timeP.push_back(source);
printf("Distance = %d",dist[destination]);
if(timeP==sP) {
printf("; Time = %d:",time[destination]);
for(int i=sP.size()-1; i>=0; i--) {
if(i==sP.size()-1) {
printf(" %d",sP[i]);
} else {
printf(" -> %d",sP[i]);
}
}
printf("\n");
} else {
printf(":");
for(int i=sP.size()-1; i>=0; i--) {
if(i==sP.size()-1) {
printf(" %d",sP[i]);
} else {
printf(" -> %d",sP[i]);
}
}
printf("\nTime = %d:",time[destination]);
for(int i=timeP.size()-1; i>=0; i--) {
if(i==timeP.size()-1) {
printf(" %d",timeP[i]);
} else {
printf(" -> %d",timeP[i]);
}
}
printf("\n");
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
int oneway,time,length,v1,v2;
vector<OnlineMap> vec[n];
for(int i=0; i<m; i++) {
scanf("%d%d%d%d%d",&v1,&v2,&oneway,&length,&time);
OnlineMap onlineA;
onlineA.vEnd = v2;
onlineA.time = time;
onlineA.length = length;
vec[v1].push_back(onlineA);
if(!oneway) {
OnlineMap onlineB;
onlineB.vEnd = v1;
onlineB.time = time;
onlineB.length = length;
vec[v2].push_back(onlineB);
}
}
scanf("%d%d",&v1,&v2);
ShortestPath(v1,v2, vec, n);
return 0;
}