hdu 2544 【总结】 Dijkstra,Bellman-Ford ,SPFA 最短路求法及对应优化

题目地址:hdu2544

就是直接求最短路  数据很弱  什么方法都可以

1 floyd 

#include<iostream>

using namespace std;

#define  INF 10000009
int d[105][105];

int n,m;

void init()
{
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            d[i][j]=(i==j?0:INF);
            
}

//   1 floyd  2 Dijkstra  3 Bellman-Ford  4 Dijkstra priority_queue  5  Bellman-Ford with queue
int main()
{
    while(cin>>n>>m)
    
    {
      
     if(n==0&&m==0)  break;
     
        init();
        
    int u,v,w;
    
    for(int i=0;i<m;i++)
    {
        cin>>u>>v>>w;
        d[u-1][v-1]=w;
        d[v-1][u-1]=w;
        
    }

    for(int k=0;k<n;k++)
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                if(d[i][k]!=INF&&d[k][j]!=INF)d[i][j]=d[i][j]<(d[i][k]+d[k][j])?d[i][j]:(d[i][k]+d[k][j]);
    
    
    cout<<d[0][n-1]<<endl;
        
    }
    
}

2 Dijkstra  赤裸裸的小白书代码

#include<iostream>

using namespace std;

#define  INF 10000009

int d[105];

int n,m;



//struct
//{
//    int u;
//    int v;
//    int w;
//    
//} e[10005];


int done[10005];

int  w[105][105];


void init()
{
    for(int i=0;i<n;i++)
        d[i]=(i==0?0:INF);
    memset(done, 0, sizeof(done));
    
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            w[i][j]=(i==j?0:INF);
    
}
//   1 floyd  2 Dijkstra  3 Bellman-Ford  4 Dijkstra priority_queue  5  Bellman-Ford with queue

int min(int a,int b)
{
    return a<b?a:b;
}

int main()
{
    while(cin>>n>>m)
    
    {
      
     if(n==0&&m==0)  break;
     
        init();
        
    int a,b,c;
    
    for(int i=0;i<m;i++)
    {
        cin>>a>>b>>c;
//        e[i].u=a-1;
//        e[i].v=b-1;
//        e[i].w=c;
        
        w[a-1][b-1]=c;
        w[b-1][a-1]=c;
        
    }
        
     // Dijkstra
    
        for(int i=0;i<n;i++)
        {
            int x;
            int m=INF;
            
            for(int y=0;y<n;y++)
                if(done[y]==0&&d[y]<=m) m=d[x=y];
            
            done[x]=1;
            
            for(int y=0;y<n;y++)
                if(w[x][y]!=INF)  d[y]=min(d[y],d[x]+w[x][y]);
            
               
        }
        
      
        cout<<d[n-1]<<endl;
        
        
        
        
        
    }
    
}

3 Dijkstra 使用优先队列优化

记住要将无向图转化为有向图

#include<iostream>
#include<utility>
#include<vector>
#include<queue>
using namespace std;

#define  INF 1000000009

typedef  pair<int, int> pii;

int d[1005];

int nxt[200010];
int first[1005];

int n,m;



struct
{
    int u;
    int v;
    int w;
    
} e[200010];


int done[1005];

//int  w[105][105];


void init()
{
    for(int i=0;i<n;i++)
        d[i]=(i==0?0:INF);
    
    memset(done, 0, sizeof(done));
    
    memset(first,-1,sizeof(first));
    
    
//    for(int i=0;i<n;i++)
//        for(int j=0;j<n;j++)
//            w[i][j]=(i==j?0:INF);
    
}



//   1 floyd  2 Dijkstra  3 Bellman-Ford  4 Dijkstra priority_queue  5  Bellman-Ford with queue

int min(int a,int b)
{
    return a<b?a:b;
}



int main()
{
    
    
    while(cin>>n>>m)
    
    {
      
     if(n==0&&m==0)  break;
     
        init();
        
    int a,b,c;
    
    for(int i=0;i<m;i++)
    {
        cin>>a>>b>>c;
        e[i].u=a-1;
        e[i].v=b-1;
        e[i].w=c;
        
        nxt[i]=first[a-1];
        first[a-1]=i;
        
        
//        w[a-1][b-1]=c;
//        w[b-1][a-1]=c;
        
    }
       
        for(int i=0;i<m;i++)
        {
            e[i+m].u=e[i].v;
            e[i+m].v=e[i].u;
            e[i+m].w=e[i].w;
            
            nxt[i+m]=first[e[i].v];
            first[e[i].v]=i+m;
    
            
        }
     // Dijkstra  with priority_queue;
        
        priority_queue<pii,vector<pii>,greater<pii> >  pq;
        
        pq.push(make_pair(d[0], 0));
        
    
        while(!pq.empty())
        {
        
            
            pii u=pq.top();
            pq.pop();
            
            int x=u.second;
            
           
            
            if(done[x])  continue;
            
            done[x]=1;
            
            for(int i=first[x];i!=-1;i=nxt[i])
               {
                       int y=e[i].v;
               
                       if(d[y]>d[x]+e[i].w)
                       {
                           d[y]=d[x]+e[i].w;
                           pq.push(make_pair(d[y],y));
                           
                       }

               }
             
                
            
            
        }
        
      
        cout<<d[n-1]<<endl;
        
        
        
        
        
    }
    
}

4 Bellman-Ford

#include<iostream>
#include<utility>
#include<vector>
#include<queue>
using namespace std;

#define  INF 1000000009

typedef  pair<int, int> pii;

int d[1005];



int n,m;



struct
{
    int u;
    int v;
    int w;
    
} e[200010];







void init()
{
    for(int i=0;i<n;i++)
        d[i]=(i==0?0:INF);
 
    
}



int min(int a,int b)
{
    return a<b?a:b;
}



int main()
{
    
    
    while(cin>>n>>m)
    
    {
      
     if(n==0&&m==0)  break;
     
        init();
        
    int a,b,c;
    
    for(int i=0;i<m;i++)
    {
        cin>>a>>b>>c;
        e[i].u=a-1;
        e[i].v=b-1;
        e[i].w=c;
   

        
    }
       
        for(int i=0;i<m;i++)
        {
            e[i+m].u=e[i].v;
            e[i+m].v=e[i].u;
            e[i+m].w=e[i].w;
            

        }
      //Bellman-Ford
        
        for(int k=0;k<n-1;k++)
        {
            for(int i=0;i<2*m;i++)
            {
                int x=e[i].u;
                int y=e[i].v;
                if(d[x]<INF)  d[y]=min(d[y],d[x]+e[i].w);
                
            }
        }
        
      
        cout<<d[n-1]<<endl;
        
        
        
        
        
    }
    
}

5 使用队列优化的Bellman-Ford (SPFA)

#include<iostream>
#include<utility>
#include<vector>
#include<queue>
using namespace std;

#define  INF 1000000009


int d[105];

int first[105];
int nxt[20005];

int  inq[105];


int n,m;



struct
{
    int u;
    int v;
    int w;
    
} e[20005];







void init()
{
    for(int i=0;i<n;i++)
        d[i]=(i==0?0:INF);
    memset(first, -1, sizeof(first));
    
    
}



int min(int a,int b)
{
    return a<b?a:b;
}



int main()
{
    
    
    while(cin>>n>>m)
    
    {
      
     if(n==0&&m==0)  break;
     
        init();
        
    int a,b,c;
    
    for(int i=0;i<m;i++)
    {
        cin>>a>>b>>c;
        e[i].u=a-1;
        e[i].v=b-1;
        e[i].w=c;
        nxt[i]=first[a-1];
        first[a-1]=i;

    }
       
        for(int i=0;i<m;i++)
        {
            e[i+m].u=e[i].v;
            e[i+m].v=e[i].u;
            e[i+m].w=e[i].w;
            nxt[i+m]=first[e[i].v];
            first[e[i].v]=i+m;
            
        }
      //Bellman-Ford  with_queue   SPFA
        
        queue<int>  q;
        q.push(0);
        
        while(!q.empty())
        {
            int x=q.front();
            q.pop();
            inq[x]=0;
            
            for(int i=first[x];i!=-1;i=nxt[i])
            {
                int y=e[i].v;
                
                if(d[y]>d[x]+e[i].w)
                {
                    d[y]=d[x]+e[i].w;
                    if(!inq[y])
                    {
                        inq[y]=1;
                        q.push(y);
                    }
                }
            }
        
        }
        cout<<d[n-1]<<endl;
        
        
        
        
        
    }
    
}

需要注意的是  因为SPFA能处理负权值  ,所以 关键是  踢出队列以后  把在inq这个标记清除了

和在Dijkstra 中,  踢出队列仍然不用做任何操作

只需要维护done数组 ,已经做过就不要再进队 出队了(出队就是“进入A集合”)  然后更新后重新进入优先队列  因为只要进入  优先级一定比更新之前的那个pair高  那么一定会先完成done[x]=1 操作 ,没有扔掉的也无所谓了。

额 

如果不喜欢向前星  用vector邻接表也行

这里还是全部重新用vector 打一遍

1用pq 维护的DIjkstra     使用vector版本

(注: 需要说明的是 ,这里的队列和SPFA里的队列完全不同 ,这里仅仅是取出当前d值最小的快速方法而SPFA里面的队列是是为了BFS)

代码:

#include<iostream>
#include<vector>
#include<utility>
#include<queue>

using namespace std;

typedef pair<int,int>  pii;


#define INF 1000000009
int d[105];
int done[105];
vector<int> G[1000];
vector<int> E[1000];

int n,m;




int min(int a,int b)
{
    return a<b?a:b;
    
}

void init()
{
    
    for(int i=0;i<n;i++)
        d[i]=(i==0?0:INF);
    
    for(int i=0;i<n;i++)   // 取代前向星
    {
      G[i].clear();
        E[i].clear();
    }
    
    
    
    memset(done, 0, sizeof(done));
    
}

int main()
{
    while(cin>>n>>m)
    {
        if(n==0&&m==0)  break;
        
        init();
        
        int u,v,w;
        
        for(int i=0;i<m;i++)
        {
            cin>>u>>v>>w;
            G[u-1].push_back(v-1);
            G[v-1].push_back(u-1);
            E[u-1].push_back(w);
            E[v-1].push_back(w);
            
        }
        
        
        // Dijkstra with priority_queue
        
        priority_queue<pii,vector<pii>,greater<pii> >pq;
        
        pq.push(make_pair(d[0], 0));
        
        while(!pq.empty())
        {
            pii u=pq.top();
            pq.pop();
            
            int x=u.second;
            
            if(done[x])  continue;
            
            done[x]=1;
            
            int s=G[x].size();
            
            for(int i=0;i<s;i++)
            {
                int y=G[x][i];
                if(d[x]+E[x][i]<d[y])
                {
                    d[y]=d[x]+E[x][i];
                    pq.push(make_pair(d[y],y));
                    
                }
                
            }
            
            
        }
        
        cout<<d[n-1]<<endl;
        
        
    }
    
}

2 SPFA   vector版本

#include<iostream>
#include<vector>
#include<queue>

using  namespace std;

#define INF 1000000009
int n,m;






int d[105];
int inq[105];
vector<int> G[105];
vector<int> E[105];


void init()
{
    for(int i=0;i<n;i++)
        d[i]=(i==0?0:INF);
    memset(inq, 0, sizeof(inq));
    for(int i=0;i<n;i++)
       
    {
        G[i].clear();
        E[i].clear();
    }
}

int min(int a,int b)
{
    return a<b?a:b;
    
}
int main()
{
    while(cin>>n>>m)
    {
        if(n==0&&m==0)  break;
        
        init();
        
        int u,v,w;
        for(int i=0;i<m;i++)
        {
            cin>>u>>v>>w;
            G[u-1].push_back(v-1);
            G[v-1].push_back(u-1);
            E[u-1].push_back(w);
            E[v-1].push_back(w);
            
            
        }
        //
        //      for(int i=0;i<m;i++)
        //      {
        //          e[i+m].u=e[i].v;
        //          e[i+m].v=e[i].u;
        //          e[i+m].w=e[i].w;
        //      }
        
        // SPFA
        
        queue<int> q;
        
        q.push(0);
        
        while(!q.empty())
        {
            int x=q.front();
            q.pop();
            inq[x]=0;
            
            int s=G[x].size();
            
            for(int i=0;i<s;i++)
            {
                int y=G[x][i];
                if(d[y]>d[x]+E[x][i])
                {
                    d[y]=d[x]+E[x][i];
                    if(!inq[y])
                    {
                        inq[y]=1;
                        q.push(y);
                    }
                }
            }
        }
        
        cout<<d[n-1]<<endl;
        
        
    }
}
    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/jingqi814/article/details/21501723
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞