【dijkstra改动】求次短路

USACO 2006 November Gold

本题目的意思就是要求次短路。我用两种方法求解:

(一)利用dijkstra算法进行适当修改,到某个顶点v的次短路:(1)其他某个顶点u的最短路加上u->v的边长;(2)其他某个顶点u的次短路加上u->v的边长。所以我们要求出到所有

           顶点的最短路和次短路。因此对每个顶点,同时记录最短距离和次短距离(开两个数组记录,用dijkstra算法不断更新)。

[cpp] 
view plain
 copy

  1. #include<queue>  
  2. #include<vector>  
  3. #include<iostream>  
  4. #include<stdio.h>  
  5. #include<string.h>  
  6. #include<algorithm>  
  7. using namespace std;  
  8.   
  9. const int INF=1000000000;  
  10. const int max_e=200000+5;  
  11. typedef pair<int,int>P;  
  12. struct edge{  
  13.     int to,dis;  
  14.     edge(int to,int dis){  
  15.         this -> to = to;  
  16.         this -> dis = dis;  
  17.     }  
  18. };  
  19. int N,R;  
  20. int a,b,c;  
  21. int dis[5005];         //记录最短路径  
  22. int disc[5005];       //记录次短路径  
  23. vector<edge>G[max_e];  
  24.   
  25. void dijkstra(){  
  26.     fill(dis+1,dis+N+1,INF);  
  27.     fill(disc+1,disc+N+1,INF);  
  28.     priority_queue<P,vector<P>,greater<P> >q;  
  29.     dis[1]=0;  
  30.     q.push(P(0,1));  
  31.     while(q.size()){  
  32.         P p=q.top();  
  33.         q.pop();  
  34.         int dd=p.first;  
  35.         int v=p.second;  
  36.         if(disc[v]<dd) continue;  
  37.         for(int i=0;i<G[v].size();i++){  
  38.             edge& e=G[v][i];  
  39.             int d=dd+e.dis;  
  40.             if(dis[e.to]>d){  
  41.                 swap(dis[e.to],d);  
  42.                 q.push(P(dis[e.to],e.to));  
  43.             }  
  44.             if(disc[e.to]>d&&dis[e.to]<d){     //这里是关键改动!
  45.                 disc[e.to]=d;  
  46.                 q.push(P(disc[e.to],e.to));  
  47.             }  
  48.         }  
  49.     }  
  50.     cout<<disc[N]<<endl;  
  51. }  
  52.   
  53. int main()  
  54. {  
  55.     scanf(“%d%d”,&N,&R);  
  56.     for(int i=1;i<=R;i++){  
  57.         scanf(“%d%d%d”,&a,&b,&c);  
  58.         G[a].push_back(edge(b,c));  
  59.         G[b].push_back(edge(a,c));  
  60.     }  
  61.     dijkstra();  
  62.     return 0;  
  63. }  

(二)一个巧妙的方法,用两次dijkstra双向求出起点到每一点的最短路,以及终点到每一点的最短路径,然后枚举每一条边,就可以得到次短路了。此方法也可以拓展成求第K短

           路问题,不过要注意时间复杂度。

[cpp] 
view plain
 copy

  1. #include<queue>  
  2. #include<vector>  
  3. #include<iostream>  
  4. #include<stdio.h>  
  5. #include<string.h>  
  6. #include<algorithm>  
  7. using namespace std;  
  8.   
  9. const int INF=1000000000;  
  10. const int max_e=200000+5;  
  11. typedef pair<int,int>P;  
  12. struct edge{  
  13.     int to,dis;  
  14.     edge(int to,int dis){  
  15.         this -> to = to;  
  16.         this -> dis = dis;  
  17.     }  
  18. };  
  19. struct dd{  
  20.     int x,y;  
  21.     int sum;  
  22. }an[200005];  
  23.   
  24. int N,R;  
  25. int a,b,c;  
  26. int d1[5005];  
  27. int d2[5005];  
  28. vector<edge>G[max_e];  
  29.   
  30. void dijkstra(int dis[],int s){  
  31.     fill(dis+1,dis+N+1,INF);  
  32.     priority_queue<P,vector<P>,greater<P> >q;  
  33.     dis[s]=0;  
  34.     q.push(P(0,s));  
  35.     while(q.size()){  
  36.         P p=q.top();  
  37.         q.pop();  
  38.         int v=p.second;  
  39.         if(dis[v]<p.first) continue;  
  40.         for(int i=0;i<G[v].size();i++){  
  41.             edge& e=G[v][i];  
  42.             if(dis[e.to]>dis[v]+e.dis){  
  43.                 dis[e.to]=dis[v]+e.dis;  
  44.                 q.push(P(dis[e.to],e.to));  
  45.             }  
  46.         }  
  47.     }  
  48. }  
  49.   
  50. int main()  
  51. {  
  52.     int K=0;  
  53.     scanf(“%d%d”,&N,&R);  
  54.     for(int i=1;i<=R;i++){  
  55.         scanf(“%d%d%d”,&a,&b,&c);  
  56.         G[a].push_back(edge(b,c));  
  57.         G[b].push_back(edge(a,c));  
  58.         an[K].x=a; an[K].y=b; an[K].sum=c; K++;  
  59.         an[K].x=b; an[K].y=a; an[K].sum=c; K++;  
  60.     }  
  61.     dijkstra(d1,1);  
  62.     dijkstra(d2,N);  
  63.     int ans=INF;    //cout<<ans<<” “<<d1[N]<<endl;  
  64.     for(int i=0;i<K;i++){  
  65.         int aa=d1[an[i].x]+d2[an[i].y]+an[i].sum;  //这里是关键!!!!
  66.         if(aa>d1[N]){   //如果大于最短路,那就比较,取最小的就是次短路 
  67.             ans=min(ans,aa);  
  68.         }  
  69.     }cout<<ans<<endl;  
  70.     return 0;  
  71. }  
    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/m0_38033475/article/details/79932498
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞