题意:给定一个图,以及起点和终点,需要我们计算两条路径。第1条路径:距离最短路径,若不唯一,则选择用时最短的那一条;第2条路径:用时最少路径,若不唯一,选择经过结点数最少的那一条。
思路:两次Dijkstra即可。以往都是求一条路径,本题要求两条,没什么不同,只是代码量多了一些。编写代码前要心中有数,变量名怎么命名等等(变量名一多,命名真是件举棋不定的事。。)
#include <cstdio> #include <vector> #include <algorithm> using namespace std; const int Inf=0x7fffffff; const int N=505; struct Node{ int v; int length,time; Node(int v_,int len_,int t_):v(v_),length(len_),time(t_){} }; int n,m,s,e;//结点个数,边数,起点,终点 vector<Node> Adj[N]; bool vis[N]; vector<int> pre[N]; //dis[v]记录起点s到结点v的最短距离(第1标尺),cost[v]记录起点s到结点v的最快时间(第2标尺)。用于求第1条路径 int dis[N]; int cost[N]; //time[v]记录起点s到结点v的最快时间(第1标尺)。用于求第2条路径 int time[N]; void Dijkstra_length(int s) { fill(vis,vis+N,false); fill(dis,dis+N,Inf); dis[s]=0; fill(cost,cost+N,Inf); cost[s]=0; for(int i=0;i<n;i++){ int u=-1,min=Inf; for(int v=0;v<n;v++){ if(!vis[v] && dis[v]<min){ min=dis[v]; u=v; } } if(u==-1) return; vis[u]=true; for(auto node:Adj[u]){//u-v int v=node.v, len=node.length, time=node.time; if(!vis[v]){ if(dis[u]+len < dis[v]){ dis[v] = dis[u]+len; cost[v] = cost[u]+time; pre[v].clear(); pre[v].push_back(u); }else if(dis[u]+len == dis[v]){ if(cost[u]+time < cost[v]){ cost[v] = cost[u]+time; pre[v].clear(); pre[v].push_back(u); } } } } } } vector<int> path_len; void dfs_length(int v) { path_len.push_back(v); for(auto u:pre[v]) dfs_length(u); } void Dijkstra_time(int s) { fill(vis,vis+N,false); fill(time,time+N,Inf); time[s]=0; for(int i=0;i<n;i++){ int u=-1,min=Inf; for(int v=0;v<n;v++){ if(!vis[v] && time[v]<min){ min=time[v]; u=v; } } if(u==-1) return; vis[u]=true; for(auto node:Adj[u]){//u-v int v=node.v, len=node.length, t=node.time; if(!vis[v]){ if(time[u]+t < time[v]){ time[v] = time[u]+t; pre[v].clear(); pre[v].push_back(u); }else if(time[u]+t == time[v]){ pre[v].push_back(u); } } } } } vector<int> path_time,tmp; int minIntersection=Inf; void dfs_time(int v) { tmp.push_back(v); if(v==s){ if(tmp.size()<minIntersection){ minIntersection=tmp.size(); path_time=tmp; } return; } for(auto u:pre[v]){ dfs_time(u); tmp.pop_back(); } } int main() { int v1,v2,one_way,len,t; scanf("%d%d",&n,&m); for(int i=0;i<m;i++){ scanf("%d%d%d%d%d",&v1,&v2,&one_way,&len,&t); if(one_way){ Adj[v1].push_back(Node(v2,len,t)); }else{ Adj[v1].push_back(Node(v2,len,t)); Adj[v2].push_back(Node(v1,len,t)); } } scanf("%d%d",&s,&e); //两次Dijkstra Dijkstra_length(s); dfs_length(e); Dijkstra_time(s); dfs_time(e); if(path_len==path_time){ printf("Distance = %d; Time = %d:",dis[e],time[e]); for(int i=path_time.size()-1;i>=0;i--){ printf(" %d",path_time[i]); if(i>0) printf(" ->"); else printf("\n"); } }else{ printf("Distance = %d:",dis[e]); for(int i=path_len.size()-1;i>=0;i--){ printf(" %d",path_len[i]); if(i>0) printf(" ->"); else printf("\n"); } printf("Time = %d:",time[e]); for(int i=path_time.size()-1;i>=0;i--){ printf(" %d",path_time[i]); if(i>0) printf(" ->"); else printf("\n"); } } return 0; }