zoukankan      html  css  js  c++  java
  • 第六章、最短路径

    第一节、只有五行的算法——Floyd-Warshall(多源最短路径)
    p152 FW算法完整代码

     1 #include <stdio.h>
     2 int main()
     3 {
     4     int e[10][10],k,i,j,n,m,t1,t2,t3;
     5     int inf=99999999; //用inf(infinity的缩写)存储一个我们认为的正无穷值
     6     //读入n和m,n表示顶点个数,m表示边的条数
     7     scanf("%d %d",&n,&m);
     8     
     9     //初始化
    10     for(i=1;i<=n;i++)
    11         for(j=1;j<=n;j++)
    12             if(i==j) e[i][j]=0;  
    13                 else e[i][j]=inf;
    14 
    15     //读入边
    16     for(i=1;i<=m;i++)
    17     {
    18         scanf("%d %d %d",&t1,&t2,&t3);
    19         e[t1][t2]=t3;
    20     }
    21     
    22     //Floyd-Warshall算法核心语句
    23     for(k=1;k<=n;k++)
    24         for(i=1;i<=n;i++)
    25             for(j=1;j<=n;j++)
    26                 //if(e[i][j]>e[i][k]+e[k][j] ) 
    27                 if(e[i][k]<inf && e[k][j]<inf && e[i][j]>e[i][k]+e[k][j])                  
    28                     e[i][j]=e[i][k]+e[k][j];
    29     
    30     //输出最终的结果
    31     for(i=1;i<=n;i++)
    32     {
    33          for(j=1;j<=n;j++)
    34         {
    35              printf("%10d",e[i][j]);
    36         }
    37         printf("
    ");
    38     }
    39     
    40     return 0;
    41 }
    42 
    43 /*
    44 
    45 4 8
    46 1 2 2
    47 1 3 6
    48 1 4 4
    49 2 3 3
    50 3 1 7
    51 3 4 1
    52 4 1 5
    53 4 3 12
    54 
    55 4 9
    56 1 2 2
    57 1 3 6
    58 1 4 4
    59 2 3 3
    60 3 1 7
    61 3 4 1
    62 4 1 5
    63 4 2 1
    64 4 3 12
    65 
    66 为测试经过任意数点,加测试数据一组
    67 */
    View Code


    添加代码,输出中间矩阵

     1 #include <stdio.h>
     2 int e[10][10],k,i,j,n,m,t1,t2,t3;
     3 
     4 void printm()
     5 {
     6     int i,j;
     7     for(i=1;i<=n;i++)
     8     {
     9          for(j=1;j<=n;j++)
    10         {
    11              printf("%5d",e[i][j]);
    12         }
    13         printf("
    ");
    14     }
    15     printf("
    ");  
    16 }
    17 
    18 int main()
    19 {
    20     int inf=999; //用inf(infinity的缩写)存储一个我们认为的正无穷值
    21     //读入n和m,n表示顶点个数,m表示边的条数
    22     scanf("%d %d",&n,&m);
    23     
    24     //初始化
    25     for(i=1;i<=n;i++)
    26         for(j=1;j<=n;j++)
    27             if(i==j) e[i][j]=0;  
    28                 else e[i][j]=inf;
    29 
    30     //读入边
    31     for(i=1;i<=m;i++)
    32     {
    33         scanf("%d %d %d",&t1,&t2,&t3);
    34         e[t1][t2]=t3;
    35     }
    36     printf("
    ");
    37     printm();
    38     
    39     //Floyd-Warshall算法核心语句
    40     for(k=1;k<=n;k++)
    41     {
    42         for(i=1;i<=n;i++)
    43             for(j=1;j<=n;j++)
    44                 //if(e[i][j]>e[i][k]+e[k][j] ) 
    45                 if(e[i][k]<inf && e[k][j]<inf && e[i][j]>e[i][k]+e[k][j])                  
    46                     e[i][j]=e[i][k]+e[k][j];
    47         printm();
    48     }
    49    
    50     return 0;
    51 }
    52   
    53 /*
    54 
    55 4 8
    56 1 2 2
    57 1 3 6
    58 1 4 4
    59 2 3 3
    60 3 1 7
    61 3 4 1
    62 4 1 5
    63 4 3 12
    64 
    65 */
    View Code


    第二节、Dijkstra算法——通过边实现松弛(单源最短路径)
    p158 Ds算法完整代码

     1 #include <stdio.h>
     2 int main()
     3 {
     4     int e[10][10],dis[10],book[10],i,j,n,m,t1,t2,t3,u,v,min;
     5     int inf=99999999; //用inf(infinity的缩写)存储一个我们认为的正无穷值
     6     //读入n和m,n表示顶点个数,m表示边的条数
     7     scanf("%d %d",&n,&m);
     8     
     9     //初始化
    10     for(i=1;i<=n;i++)
    11         for(j=1;j<=n;j++)
    12             if(i==j) e[i][j]=0;  
    13               else e[i][j]=inf;
    14               
    15     //读入边
    16     for(i=1;i<=m;i++)
    17     {
    18         scanf("%d %d %d",&t1,&t2,&t3);
    19         e[t1][t2]=t3;
    20     }
    21 
    22     //初始化dis数组,这里是1号顶点到其余各个顶点的初始路程
    23     for(i=1;i<=n;i++)
    24         dis[i]=e[1][i];
    25 
    26     //book数组初始化
    27     for(i=1;i<=n;i++)
    28         book[i]=0;
    29     book[1]=1;
    30     
    31     //Dijkstra算法核心语句
    32     for(i=1;i<=n-1;i++)
    33     {
    34         //找到离1号顶点最近的顶点
    35         min=inf;
    36         for(j=1;j<=n;j++)
    37         {
    38             if(book[j]==0 && dis[j]<min) //在集合Q中找到最近的顶点
    39             {
    40                 min=dis[j];
    41                 u=j; //记录下顶点位置
    42             }
    43         }
    44         book[u]=1; //顶点u加入集合P
    45         for(v=1;v<=n;v++)
    46         {
    47             if(e[u][v]<inf) //对每个出边指向点
    48             {
    49                 if(dis[v]>dis[u]+e[u][v]) 
    50                     dis[v]=dis[u]+e[u][v]; //松弛
    51             }
    52         }    
    53     }
    54     
    55     //输出最终的结果
    56     for(i=1;i<=n;i++)
    57         printf("%d ",dis[i]);
    58         
    59     getchar();
    60     getchar();
    61     return 0;
    62 }
    63 
    64 /*
    65 
    66 6 9
    67 1 2 1
    68 1 3 12
    69 2 3 9
    70 2 4 3
    71 3 5 5
    72 4 3 4
    73 4 5 13
    74 4 6 15
    75 5 6 4
    76 
    77 */
    View Code


    输出中间dis数组

     1 #include <stdio.h>
     2 int main()
     3 {
     4     int e[10][10],dis[10],book[10],i,j,n,m,t1,t2,t3,u,v,min;
     5     int inf=999; //用inf(infinity的缩写)存储一个我们认为的正无穷值
     6     //读入n和m,n表示顶点个数,m表示边的条数
     7     scanf("%d %d",&n,&m);
     8     
     9     //初始化
    10     for(i=1;i<=n;i++)
    11         for(j=1;j<=n;j++)
    12             if(i==j) e[i][j]=0;  
    13               else e[i][j]=inf;
    14               
    15     //读入边
    16     for(i=1;i<=m;i++)
    17     {
    18         scanf("%d %d %d",&t1,&t2,&t3);
    19         e[t1][t2]=t3;
    20     }
    21 
    22     //初始化dis数组,这里是1号顶点到其余各个顶点的初始路程
    23     for(i=1;i<=n;i++)
    24         dis[i]=e[1][i];
    25 
    26     //book数组初始化
    27     for(i=1;i<=n;i++)
    28         book[i]=0;
    29     book[1]=1;
    30 
    31         for(j=1;j<=n;j++)
    32             printf("%5d",dis[j]);
    33         printf("
    "); //
    34     
    35     //Dijkstra算法核心语句
    36     for(i=1;i<=n-1;i++)
    37     {
    38         //找到离1号顶点最近的顶点
    39         min=inf;
    40         for(j=1;j<=n;j++)
    41         {
    42             if(book[j]==0 && dis[j]<min) //在集合Q中找到最近的顶点
    43             {
    44                 min=dis[j];
    45                 u=j; //记录下顶点位置
    46             }
    47         }
    48         book[u]=1; //顶点u加入集合P
    49         for(v=1;v<=n;v++)
    50         {
    51             if(e[u][v]<inf) //对每个出边指向点
    52             {
    53                 if(dis[v]>dis[u]+e[u][v]) 
    54                     dis[v]=dis[u]+e[u][v]; //松弛
    55             }
    56         }
    57         for(j=1;j<=n;j++)
    58             printf("%5d",dis[j]);
    59         printf("
    "); //
    60     }
    61        
    62     getchar(); getchar();
    63     return 0;
    64 }
    65 
    66 /*
    67 
    68 6 9
    69 1 2 1
    70 1 3 12
    71 2 3 9
    72 2 4 3
    73 3 5 5
    74 4 3 4
    75 4 5 13
    76 4 6 15
    77 5 6 4
    78 
    79 */
    View Code


    p160 邻接表的数组方法(不用链表)
    以下这个博客中的内容,比书中说得更清楚:
    http://www.cnblogs.com/ahalei/p/3651334.html
    代码:

     1 #include <stdio.h>
     2 int main()
     3 {
     4     int n,m,i,k;
     5     //u、v和w的数组大小要根据实际情况来设置,要比m的最大值要大1
     6     int u[60],v[60],w[60];
     7     //first和next的数组大小要根据实际情况来设置,要比n的最大值要大1
     8     int first[50],next[50];
     9     scanf("%d %d",&n,&m);
    10     //初始化first数组下标1~n的值为-1,表示1~n顶点暂时都没有边
    11     for(i=1;i<=n;i++)
    12         first[i]=-1;
    13     for(i=1;i<=m;i++)
    14     {
    15         scanf("%d %d %d",&u[i],&v[i],&w[i]);//读入每一条边
    16         //下面两句是关键啦
    17         next[i]=first[u[i]];
    18         first[u[i]]=i;
    19     }
    20 
    21     for(i=1;i<=n;i++)
    22     {
    23         k=first[i];
    24         while(k!=-1)
    25         {
    26             printf("%d is : %d %d %d
    ",i,u[k],v[k],w[k]);
    27             k=next[k];
    28         }
    29         printf("
    ");
    30     }  
    31 
    32     getchar();  getchar();
    33     return 0;
    34 }
    35 
    36 /*
    37 
    38 4 5
    39 1 4 9
    40 4 3 8
    41 1 2 5
    42 2 4 6
    43 1 3 7
    44 
    45 p155 的图,第二组测试数据
    46 
    47 6 9
    48 1 2 1
    49 1 3 12
    50 2 3 9
    51 2 4 3
    52 3 5 5
    53 4 3 4
    54 4 5 13
    55 4 6 15
    56 5 6 4
    57 
    58 */
    View Code


    第三节、Bellman-Ford算法——解决负权边
    p168 BF算法完整代码

     1 #include <stdio.h>
     2 int main()
     3 {
     4     int dis[10],i,k,n,m,u[10],v[10],w[10];
     5     int inf=99999999; //用inf(infinity的缩写)存储一个我们认为的正无穷值
     6     //读入n和m,n表示顶点个数,m表示边的条数
     7     scanf("%d %d",&n,&m);
     8   
     9     //读入边
    10     for(i=1;i<=m;i++)
    11         scanf("%d %d %d",&u[i],&v[i],&w[i]);
    12 
    13     //初始化dis数组,这里是1号顶点到其余各个顶点的初始路程
    14     for(i=1;i<=n;i++)
    15         dis[i]=inf;
    16     dis[1]=0;
    17 
    18     //Bellman-Ford算法核心语句
    19     for(k=1;k<=n-1;k++)
    20       for(i=1;i<=m;i++)
    21         if( dis[v[i]] > dis[u[i]] + w[i] )
    22           dis[v[i]] = dis[u[i]] + w[i];
    23 
    24     //输出最终的结果
    25     for(i=1;i<=n;i++)
    26         printf("%d ",dis[i]);
    27         
    28     getchar();
    29     getchar();
    30     return 0;
    31 }
    32 
    33 /*
    34 
    35 5 5
    36 2 3 2
    37 1 2 -3
    38 1 5 5
    39 4 5 2
    40 3 4 3
    41 
    42 */
    View Code


    输出中间结果

     1 #include <stdio.h>
     2 int main()
     3 {
     4     int dis[10],i,k,n,m,u[10],v[10],w[10];
     5     int inf=999; //用inf(infinity的缩写)存储一个我们认为的正无穷值
     6     //读入n和m,n表示顶点个数,m表示边的条数
     7     scanf("%d %d",&n,&m);
     8   
     9     //读入边
    10     for(i=1;i<=m;i++)
    11         scanf("%d %d %d",&u[i],&v[i],&w[i]);
    12 
    13     //初始化dis数组,这里是1号顶点到其余各个顶点的初始路程
    14     for(i=1;i<=n;i++)
    15         dis[i]=inf;
    16     dis[1]=0;
    17 
    18     //Bellman-Ford算法核心语句
    19     for(k=1;k<=n-1;k++)
    20     {
    21       for(i=1;i<=m;i++)
    22         if( dis[v[i]] > dis[u[i]] + w[i] )
    23           dis[v[i]] = dis[u[i]] + w[i];
    24       //输出中间结果
    25       for(i=1;i<=n;i++)
    26           printf("%5d",dis[i]);
    27       printf("
    ");
    28     }
    29         
    30     getchar(); getchar();
    31     return 0;
    32 }
    33 
    34 /*
    35 
    36 5 5
    37 2 3 2
    38 1 2 -3
    39 1 5 5
    40 4 5 2
    41 3 4 3
    42 
    43 测试p155的图
    44 
    45 6 9
    46 1 2 1
    47 1 3 12
    48 2 3 9
    49 2 4 3
    50 4 3 4
    51 3 5 5
    52 4 5 13
    53 4 6 15
    54 5 6 4
    55 
    56 与读入边的顺序,很有关系:
    57 
    58 6 9
    59 4 6 15
    60 5 6 4
    61 2 4 3
    62 4 3 4
    63 3 5 5
    64 4 5 13
    65 1 2 1
    66 1 3 12
    67 2 3 9
    68 
    69 */
    View Code


    p170 BF算法改进代码,可判断是否含有负权回路

     1 #include <stdio.h>
     2 int main()
     3 {
     4     int dis[10],i,k,n,m,u[10],v[10],w[10];
     5     int bak[10],check,flag; //
     6     int inf=99999999; //用inf(infinity的缩写)存储一个我们认为的正无穷值
     7     //读入n和m,n表示顶点个数,m表示边的条数
     8     scanf("%d %d",&n,&m);
     9   
    10     //读入边
    11     for(i=1;i<=m;i++)
    12         scanf("%d %d %d",&u[i],&v[i],&w[i]);
    13 
    14     //初始化dis数组,这里是1号顶点到其余各个顶点的初始路程
    15     for(i=1;i<=n;i++)
    16         dis[i]=inf;
    17     dis[1]=0;
    18 
    19     //Bellman-Ford算法核心语句
    20     for(k=1;k<=n-1;k++)
    21     {
    22       //备份
    23       for(i=1;i<=n;i++) bak[i]=dis[i];
    24       //松弛
    25       for(i=1;i<=m;i++)
    26         if( dis[v[i]] > dis[u[i]] + w[i] )
    27           dis[v[i]] = dis[u[i]] + w[i];
    28       //检测dis数组是否有更新
    29       check=0;
    30       for(i=1;i<=n;i++)
    31         if(bak[i]!=dis[i]) 
    32         {
    33           check=1;
    34           break;
    35         }
    36       if(check==0) break; //如无更新,跳出循环
    37     }
    38     //检测负权回路
    39     flag=0;
    40     for(i=1;i<=m;i++)
    41       if(dis[v[i]] > dis[u[i]]+w[i]) flag=1;
    42         
    43     if(flag==1) printf("have fqhl");
    44     else
    45     {
    46       //输出最终的结果
    47       for(i=1;i<=n;i++)
    48         printf("%d ",dis[i]);
    49     }    
    50     getchar();  getchar();
    51     return 0;
    52 }
    53 
    54 /*
    55 
    56 5 6
    57 2 3 2
    58 1 2 -3
    59 1 5 5
    60 4 5 2
    61 3 4 3
    62 4 3 -8
    63 
    64 */
    View Code


    第四节、BF算法的队列优化
    p174 BF算法的队列优化代码

     1 #include <stdio.h>
     2 int main()
     3 {
     4   int n,m,i,k;
     5   int u[8],v[8],w[8];
     6   int first[6],next[8];
     7   int dis[6]={0},book[6]={0};
     8   int que[101]={0},head=1,tail=1;
     9   int inf=99999999;
    10   
    11   //读入n和m,n表示顶点个数,m表示边的条数
    12   scanf("%d %d",&n,&m);
    13   
    14   //初始化dis数组,这里是1号顶点到其余各个顶点的初始路程
    15   for(i=1;i<=n;i++)
    16     dis[i]=inf;
    17   dis[1]=0;  
    18   
    19   for(i=1;i<=n;i++) book[i]=0;
    20     
    21   for(i=1;i<=n;i++) first[i]=-1;
    22   
    23   //读入边
    24   for(i=1;i<=m;i++)
    25   {
    26     scanf("%d %d %d",&u[i],&v[i],&w[i]);
    27     //
    28     next[i]=first[u[i]];
    29     first[u[i]]=i;
    30   }
    31 
    32   que[tail]=1; tail++;
    33   book[1]=1;
    34   
    35   while(head<tail)
    36   {
    37     k=first[que[head]];
    38     while(k!=-1)
    39     {
    40       if( dis[v[k]] > dis[u[k]] + w[k] )
    41       {
    42         dis[v[k]] = dis[u[k]] + w[k];
    43         //
    44         if(book[v[k]]==0)
    45         {
    46           que[tail]=v[k];
    47           tail++;
    48           book[v[k]]=1;
    49         }
    50       }
    51       k=next[k];
    52     }
    53     book[que[head]]=0;
    54     head++;
    55   }
    56   
    57   //输出最终的结果
    58   for(i=1;i<=n;i++)
    59     printf("%d ",dis[i]);
    60   getchar();  getchar();
    61   return 0;
    62 }
    63 
    64 /*
    65 
    66 5 7
    67 1 2 2
    68 1 5 10
    69 2 3 3
    70 2 5 7
    71 3 4 4
    72 4 5 5
    73 5 3 6
    74 
    75 */
    View Code





    oj
    以后整理。。。




    top

  • 相关阅读:
    activiti07- Task
    Activiti-06-.事件
    Activiti-05-.Deployment and MN 2.0 Introduction
    Spring-Hibernate-web的延迟加载方案
    Spring-Struts2-基本集成
    Spring-hibernate-BaseDao
    Spring-hibernate
    Spring-java-模板设计模式
    搭建apache,指定MPM模式为worker(不许用yum安装)
    apache + tomcat负载均衡搭建
  • 原文地址:https://www.cnblogs.com/xin-le/p/4040118.html
Copyright © 2011-2022 走看看