hdoj-2544 最短路【最短路径--dijkstra&&spfa&&floyd】

分析:纯最短路径问题。

#include<cstdio>
#include<cstring>
#define max 1010
#define INF 0x3f3f3f  //表示无穷大

int map[max][max],n;//map中存储长度,即是花费的时间

void dijkstra(int start,int end)
{
    int dis[max], visit[max]; //dis[]是距离,,visit[]是访问标记,即选中为前驱的点,去除
    int i,j,min,next=start;

    for(i=1;i<=n;++i)
    {
        dis[i]=map[start][i];  //把start到各个点的距离 存储到dis[]中
        visit[i]=0;
    }

    visit[start]=1; //标记

    for(i=1;i<=n;++i)
    {
        min=INF;
        for(j=1;j<=n;++j)  //选择最小的点作为前驱
        {
            if(!visit[j] && min>dis[j])
            {
                next=j;
                min=dis[j];
            }
        }
        visit[next]=1;  //把前驱点 标记

        for(j=1;j<=n;++j)
        {
            if(!visit[j]) //没有被标记
            {
                if(dis[j]>dis[next]+map[next][j])  //dis[next]是前驱点,map[next][j]是通过前驱点往前延伸
                {
                    dis[j]=dis[next]+map[next][j];    //更新距离

                }
            }
        }
    }
    printf("%d\n",dis[end]);
}

int main()
{
    int m,i,j,a,b,d,p,start,end;
    while(scanf("%d%d",&n,&m)&&n||m)
    {
        for(i=1;i<=n;++i) //顶点编号
        {
            for(j=1;j<=n;++j)
            {
                if(i==j)
                    map[i][j]=0;//map中存储距离
                else
                    map[i][j]=INF;
            }
        }

        while(m--)   //m行数据,完成输入花费时间
        {
            scanf("%d%d%d",&a,&b,&d);//a和b之间的距离,距离为d
            if(map[a][b] > d) //map[][]中存储无穷大
            {
                map[a][b]=map[b][a]=d;
            }

        }
        start=1,end=n;//输出开始的点,和结束的点
        dijkstra(start,end);
    }
    return 0;
}

其他人解法:

spfa:

[plain]  view plain  copy
  1. #include<cstdio>  
  2. #include<cstring>  
  3. #include<queue>  
  4. #define INF 0x3f3f3f3f  
  5. #define MAXN 100+10//点数   
  6. #define MAXM 20000+10//边数   
  7. using namespace std;  
  8. int n,m,top,vis[MAXN],dis[MAXN],visit[MAXN],head[MAXN];  
  9.   
  10. struct node {  
  11.     int from,to,val,next;  
  12. };  
  13. node edge[MAXM];  
  14.   
  15. void init()//初始化邻接表   
  16. {  
  17.     top=0;//建表从零开始  
  18.     memset(head,-1,sizeof(head));  
  19. }  
  20.   
  21. void add(int u,int v,int w)//建立邻接表  
  22. {  
  23.     edge[top].from=u;  
  24.     edge[top].to=v;  
  25.     edge[top].val=w;  
  26.     edge[top].next=head[u];  
  27.     head[u]=top++;  
  28. }  
  29.   
  30.   
  31. void spfa(int s)//s为源点  
  32. {  
  33.     queue<int>q;//存储每次入队的点  
  34.     memset(vis,0,sizeof(vis));  
  35.     memset(dis,INF,sizeof(dis));//存储源点 到这个点的最短路  
  36.     vis[s]=1;//表示这个点是否在队列里面  
  37.     dis[s]=0;  
  38.     q.push(s);  
  39.     while(!q.empty())  
  40.     {  
  41.         int u=q.front();  
  42.         q.pop();  
  43.         vis[u]=0;//该点之后还可能进入队列    消除标记    
  44.         for(int i=head[u];i!=-1;i=edge[i].next)//遍历以u为起点的 所有边  
  45.         {  
  46.             int v=edge[i].to;  
  47.             if(dis[v]>dis[u]+edge[i].val)  
  48.             {  
  49.                 dis[v]=dis[u]+edge[i].val;\  
  50.                 if(!vis[v])  
  51.                 {  
  52.                     q.push(v);  
  53.                     vis[v]=1;  
  54.                 }  
  55.             }  
  56.         }  
  57.     }  
  58.     printf("%d\n",dis[n]);  
  59. }  
  60.   
  61. void getmap()  
  62. {  
  63.     while(m--)  
  64.     {  
  65.         int a,b,c;  
  66.         scanf("%d%d%d",&a,&b,&c);  
  67.         add(a,b,c);  
  68.         add(b,a,c);//无向图  既可由a->b,也可由b->a;   
  69.     }  
  70.       
  71. }  
  72.   
  73. int main()  
  74. {  
  75.     while(scanf("%d%d",&n,&m),n|m)//n|m位运算符  n==0&&m==0时输入结束   
  76.     {  
  77.         init();  
  78.         getmap();  
  79.         spfa(1);  
  80.       
  81.     }  
  82.     return 0;  
  83. }  

floyd:

[plain]  view plain  copy
  1. #include<stdio.h>  
  2. #define INF 0x3f3f3f3f  
  3. int n,m,path[110][110];  
  4.   
  5. void init()  
  6. {  
  7.     for(int i=1;i<=n;i++)  
  8.         for(int j=1;j<=n;j++)  
  9.         {  
  10.             if(i==j)  
  11.                 path[i][j]=0;  
  12.             else path[i][j]=INF;  
  13.         }  
  14. }  
  15.   
  16. void floyd()  
  17. {  
  18.     int i,j,k;  
  19.     for(k=1;k<=n;k++)//K是穷举i,j的断点  必须是最外层表示断点   
  20.         for(i=1;i<=n;i++)  
  21.             for(j=1;j<=n;j++)  
  22.             {  
  23.                 if(path[i][j]>path[i][k]+path[k][j])  
  24.                     path[i][j]=path[i][k]+path[k][j];  
  25.             }  
  26. }  
  27.   
  28. void getmap()  
  29. {  
  30.     int a,b,c;  
  31.     while(m--)  
  32.     {  
  33.         scanf("%d%d%d",&a,&b,&c);  
  34.         if(path[a][b]>c)//防止重复  一开始初始化为INF 若已经选过 则不满足if   
  35.             path[a][b]=path[b][a]=c;  
  36.     }  
  37. }  
  38.   
  39. int main()  
  40. {  
  41.     while(scanf("%d%d",&n,&m),n|m)  
  42.     {  
  43.         init();  
  44.         getmap();  
  45.         floyd();  
  46.         printf("%d\n",path[1][n]);  
  47.     }  
  48.     return 0;  
  49. }  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值