zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",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
    ",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
    ",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
    ",d[n]);
    53     }
    54     return 0;
    55 }
    View Code
  • 相关阅读:
    Linux 下升级python和安装pip
    All of Me
    MangataのACM模板
    HDU1517 A Multiplication Game (博弈论+思维)
    Home_W的握手问题(思维+打表)
    Home_W的几何题 (计算几何)
    stone (组合数学 + Lucas定理)
    随笔分类
    HDU 5586 Sum (预处理 + 动态规划)
    POJ2104 K-th Number (平方分割 + 二分)
  • 原文地址:https://www.cnblogs.com/wuyuewoniu/p/4419535.html
Copyright © 2011-2022 走看看