Book 最短路算法

用HDU2544整理一下最近学的最短路算法

1.Dijkstra算法

原理:集合S表示已经找到最短路径的点,d[]表示当前各点到源点的距离  

        初始时,集合里面只有源点,当每个点u进入集合S时,用d[u]+w[u][v]更新距离

        再重复这个步骤,选取S外所有点中d[]最小的进入集合

       直到所有的点都进入S集合

局限性:图的边权必须为正

复杂度:O(V*V),堆优化((E+V)logV)

(1)用邻接矩阵实现

 1 #include<iostream>  

 2 #include<cstdio>  

 3 #include<cstring> 

 4 #include <cmath> 

 5 #include<stack>

 6 #include<vector>

 7 #include<map> 

 8 #include<set>

 9 #include<queue> 

10 #include<algorithm>  

11 using namespace std;

12 

13 typedef long long LL;

14 const int INF = (1<<30)-1;

15 const int mod=1000000007;

16 const int maxn=10005;

17 int w[maxn][maxn],d[maxn],used[maxn];

18 int n,m;

19 

20 void dijkstra(int s){

21     memset(used,0,sizeof(used));

22     for(int i=1;i<=n;i++) d[i]=INF;

23     d[s]=0;

24     

25     for(int k=1;k<=n;k++){

26         int p,m=INF;

27         for(int i=1;i<=n;i++) if(!used[i]&&d[i]<m) m=d[p=i];

28         used[p]=1;

29         for(int i=1;i<=n;i++) d[i]=min(d[i],d[p]+w[p][i]);

30     }

31 }

32 

33 int main(){

34     int a,b,c;

35     while(scanf("%d %d",&n,&m)!=EOF&&n&&m){

36         for(int i=1;i<=n;i++){

37             for(int j=1;j<=n;j++){

38                 if(i==j) w[i][j]=0;

39                 else w[i][j]=INF;

40             }            

41         }

42         

43         for(int i=1;i<=m;i++){

44             scanf("%d %d %d",&a,&b,&c);

45             w[a][b]=w[b][a]=c;

46         }

47         dijkstra(1);

48         printf("%d\n",d[n]);



49     }

50     return 0;

51 }
View Code

(2)用邻接表实现

注意记得每次调用dijkstra()时,first[]置为-1

 1 #include<iostream>  

 2 #include<cstdio>  

 3 #include<cstring> 

 4 #include <cmath> 

 5 #include<stack>

 6 #include<vector>

 7 #include<map> 

 8 #include<set>

 9 #include<queue> 

10 #include<algorithm>  

11 using namespace std;

12 

13 typedef long long LL;

14 const int INF = (1<<30)-1;

15 const int mod=1000000007;

16 const int maxn=10005;

17 int d[maxn],used[maxn],firstt[maxn],nextt[maxn];

18 int n,m,ecnt;

19 

20 struct edge{

21     int v,cost;

22 } e[maxn];

23 

24 void dijkstra(int s){

25     memset(used,0,sizeof(used));

26     for(int i=1;i<=n;i++) d[i]=INF;

27     d[s]=0;

28     

29     for(int k=1;k<=n;k++){

30         int p,m=INF;

31         for(int i=1;i<=n;i++) if(!used[i]&&d[i]<m) m=d[p=i];

32         used[p]=1;

33         for(int i=firstt[p];i!=-1;i=nextt[i]){

34             int v=e[i].v;

35             if(d[v]>d[p]+e[i].cost) 

36             d[v]=d[p]+e[i].cost;

37         }

38     }

39 }

40 

41 void addedges(int u,int v,int w){

42     nextt[++ecnt]=firstt[u];

43     e[ecnt].v=v;

44     e[ecnt].cost=w;

45     firstt[u]=ecnt;    

46 }

47 

48 int main(){

49     int a,b,c;

50     while(scanf("%d %d",&n,&m)!=EOF&&n&&m){

51         ecnt=0;

52         memset(firstt,-1,sizeof(firstt));

53         

54         for(int i=1;i<=m;i++){

55             scanf("%d %d %d",&a,&b,&c);

56             addedges(a,b,c);

57             addedges(b,a,c);

58         }

59         dijkstra(1);

60         printf("%d\n",d[n]);

61     }

62     return 0;

63 }
View Code

 (3)堆(优先队列)优化
参看紫书上的解释,STL中的pair是专门将两个类型捆绑起来的,

而且pair定义了它自己的排序规则,先比较第一维,相等时才比较第二维,所以需要按照(d[i],i)的顺序组合。

 1 #include<iostream>  

 2 #include<cstdio>  

 3 #include<cstring> 

 4 #include <cmath> 

 5 #include<stack>

 6 #include<vector>

 7 #include<map> 

 8 #include<set>

 9 #include<queue> 

10 #include<algorithm>  

11 #define MP(a,b) make_pair(a,b)

12 using namespace std;

13 

14 typedef long long LL;

15 typedef pair<int,int> pii;

16 const int INF = (1<<30)-1;

17 const int mod=1000000007;

18 const int maxn=100005;

19 int d[maxn],firstt[maxn],nextt[maxn];

20 int n,m,ecnt;

21 

22 struct edge{

23     int v,cost;

24     friend bool operator < (edge a,edge b){

25         return a.cost>b.cost;

26     }

27 }e[maxn];

28 

29 void addedges(int u,int v,int c){

30     nextt[++ecnt]=firstt[u];

31     e[ecnt].v=v;

32     e[ecnt].cost=c;

33     firstt[u]=ecnt;

34 }

35 

36 void dijkstra(int s){

37     priority_queue<pii> pq;

38     for(int i=1;i<=n;i++) d[i]=INF;

39     d[s]=0;

40     pq.push(MP(d[s],1));

41     while(!pq.empty()){

42         pii x=pq.top();pq.pop();

43         if(d[x.second]<x.first) continue;//当前状态没有现在dis[]数组里面的优,所以不用再继续判断下去 

44         for(int i=firstt[x.second];i!=-1;i=nextt[i]){

45             int v=e[i].v;

46             if(d[v]>d[x.second]+e[i].cost){

47                 d[v]=d[x.second]+e[i].cost;

48                 pq.push(MP(d[v],v));

49             }            

50         }        

51     }

52 }

53 

54 int main(){

55     int a,b,c;

56     while(scanf("%d %d",&n,&m)!=EOF&&n&&m){

57         memset(firstt,-1,sizeof(firstt));

58         ecnt=0;

59         for(int i=1;i<=m;i++){

60             scanf("%d %d %d",&a,&b,&c);

61             addedges(a,b,c);

62             addedges(b,a,c);

63         }

64         dijkstra(1);

65         printf("%d\n",d[n]);

66     }

67     return 0;

68 }
View Code

 (4)用vector存图实现的

 1 #include<iostream>  

 2 #include<cstdio>  

 3 #include<cstring> 

 4 #include <cmath> 

 5 #include<stack>

 6 #include<vector>

 7 #include<map> 

 8 #include<set>

 9 #include<queue> 

10 #include<algorithm>  

11 using namespace std;

12 

13 typedef long long LL;

14 const int INF = (1<<30)-1;

15 const int mod=1000000007;

16 const int maxn=10005;

17 int d[maxn];

18 

19 typedef struct edge{

20     int to,distance;

21     edge(){}

22     edge(int to,int distance) :to(to),distance(distance){}

23 };

24 typedef pair<int,int> P;

25 vector<edge> G[maxn];

26 int n,m,k;

27 

28 void dijkstra(int s){

29     

30     priority_queue<P,vector<P> ,greater<P> > q;

31     for(int i=0;i < n;i++) d[i]=INF;

32     d[s]=0;

33     q.push(P(0,s));

34     

35     while(!q.empty()){

36         P p=q.top();q.pop();

37         int v=p.second;

38         if(d[v]<p.first) continue;

39         for(int i=0;i<G[v].size();i++){

40             edge e=G[v][i];

41         

42             if(d[e.to] > d[v]+e.distance){

43             

44                 d[e.to] = d[v]+e.distance;

45                 q.push(P(d[e.to],e.to));

46             }    

47         }

48     }

49 }

50 

51 int main(){

52     while(scanf("%d %d",&n,&m)!=EOF){

53         if(n==0&&m==0) break;

54             for(int i=0;i<n;i++) G[i].clear();

55         while(m--){

56             int u,v,w;

57             scanf("%d %d %d",&u,&v,&w);

58             u--;v--;

59             G[u].push_back(edge(v,w));

60             G[v].push_back(edge(u,w));            

61         }

62         dijkstra(0);

63         printf("%d\n",d[n-1]);

64     }

65         

66     return 0;

67 }
View Code

 

2.Bellman_Ford算法

原理:对于图G(V,E),Bellman_Ford是对整个图进行V-1次松弛,每次松弛检查每条边,如果d[v]>d[u]+cost,那么则更新d[v]

应用:可以用来判断负环, 如果没有负权回路的话,那么任意两点间的路径最多经过n-2个点,

         即最多松弛n-1次,如果有负权回路,那么第n次松弛操作仍然会成功。

复杂度:O(VE)

 1 #include<iostream>  

 2 #include<cstdio>  

 3 #include<cstring> 

 4 #include <cmath> 

 5 #include<stack>

 6 #include<vector>

 7 #include<map> 

 8 #include<set>

 9 #include<queue> 

10 #include<algorithm>  

11 using namespace std;

12 

13 typedef long long LL;

14 const int INF = (1<<30)-1;

15 const int mod=1000000007;

16 const int maxn=100005;

17 int d[maxn];

18 int n,m,ecnt;

19 

20 struct edge{

21     int u,v,cost;

22 } e[maxn];

23 

24 void addedges(int u,int v,int c){

25     e[++ecnt].u=u;

26     e[ecnt].v=v;

27     e[ecnt].cost=c;    

28 }

29 

30 void Bellman_Ford(int s){

31     for(int i=1;i<=n;i++) d[i]=INF;

32     d[s]=0;

33     

34     for(int i=1;i<n;i++){

35         for(int j=1;j<=ecnt;j++){

36             if(d[e[j].v]>d[e[j].u]+e[j].cost)

37             d[e[j].v]=d[e[j].u]+e[j].cost;

38         }

39     }

40 }

41 

42 int main(){

43     int a,b,c;

44     while(scanf("%d %d",&n,&m)!=EOF&&n&&m){

45         ecnt=0;

46         for(int i=1;i<=m;i++){

47             scanf("%d %d %d",&a,&b,&c);

48             addedges(a,b,c);

49             addedges(b,a,c);

50         }

51         Bellman_Ford(1);

52         printf("%d\n",d[n]);

53     }

54     return 0;

55 }
View Code

 

你可能感兴趣的:(最短路)