最短路

数据结构与算法 —— 最短路径Dijkstra算法(迪杰斯特拉)详细图解以及python实现 前两章我们讲到了关于图的基本知识,和广度/深度优先搜索。本章,我们将介绍加权图和最短路径的相关知识。最短路径和最小生成树是图论中常见的问题。最短路径是指在一个图中找到两个节点之间的最短路径,最小生成树是指在一个图中找到一个连通子图,使得所有节点都能够互相到达,且总权值最小。最短路径算法常见的有floyd算法(弗洛伊德算法)和 dijkstra算法(迪杰斯特拉)。本文只介绍dijkstra算法。最短路径运用非常广泛,比如在导航系统中,确定两个地点间哪条路线最短; 阅读详情

 

最短路径问题旨在寻找图中两节点之间的最短路径,常用的算法有以下四种。注意是把图处理成无向还是有向

Dijkstra's (权值非负)
1 Dijkstra's算法解决的是图中单个源点到其它顶点的最短路径。只能解决权值非负
2 Dijkstral只能求出任意点到达源点的最短距离(不能求出任意两点之间的最短距离),同时适用于有向图和无向图,复杂度为O(n^2).
3算法的过程: 
1设置顶点集合S并不断的作贪心选择来选择扩充这个集合。一个顶点属于集合S当且仅当从源点到该点的最短路径长度已知
2 初始时,S中仅含有源。设U是G的某一个顶点,把从源到U且中间只经过S中的顶点的路称为从源到U的特殊路径,并用dis数组距离当前每一个顶点所对应的最短特殊路径
3Dijkstra算法每一次从V-S中取出具有最短特殊长度的顶点u,将u添加到S中,同时对dis数组进行修改。一旦S包含了所有的V中的顶点,dis数组就记录了从源点到其它顶点的最短路径长度。
4 模板:
没有优化,时间复杂度o(n^2)

 

[cpp] view plaincopy

  1. #define MAXN 1010   
  2. #define INF 0xFFFFFFF   
  3. int  value[MAXN][MAXN];/*保存的是边权值*/  
  4. int  dis[MAXN];/*保存源点到任意点之间的最短路*/  
  5. int  father[MAXN];/*保存i点的父亲节点*/  
  6. int  vis[MAXN];/*记录顶点是否没取过*/   
  7.   
  8. void input(){       
  9.       int star , end , v;  
  10.       scanf("%d%d" , &n , &m);  
  11.       /*初始化value数组*/  
  12.      for(int i = 1 ; i <= n ; i++){  
  13.          for(int j = 1; j <= n ; j++)  
  14.              value[i][j] = INF;  
  15.      }  
  16.     for(int i = 0 ; i < m ; i++){  
  17.         scanf("%d%d%d" ,  &star , &end , &v);  
  18.         if(value[star][end] == INF)  
  19.             value[star][end] = value[end][star] = v;/*处理成无向图*/  
  20.         else{  
  21.             if(v < value[star][end])/*判断重边是否出现*/  
  22.                  value[star][end] = value[end][star] = v;  
  23.         }  
  24. }  
  25.   
  26. void dijkstra(int s){  
  27.      memset(vis , 0 , sizeof(vis));  
  28.      memset(father , 0 , sizeof(father));  
  29.      /*初始化dis数组*/  
  30.      for(int i = 1 ; i<= n ; i++)  
  31.           dis[i] = INF;  
  32.      dis[s] = 0;  
  33.      for(int i = 1 ; i <= n ; i++){/*枚举n个顶点*/  
  34.         int pos;  
  35.         pos = -1;  
  36.         for(int j = 1 ; j <= n ;j++){/*找到未加入集合的最短路点*/  
  37.            if(!vis[j] && (pos == -1 || dis[j] < dis[pos]))  
  38.               pos = j;  
  39.         }  
  40.         vis[pos] = 1;/*把这个点加入最短路径集合*/  
  41.         for(int j = 1 ; j <= n ; j++){/*更新dis数组*/  
  42.            if(!vis[j] && (dis[j] > dis[pos] + value[pos][j])){  
  43.              dis[j] = dis[pos] + value[pos][j];  
  44.              father[j] = pos;  
  45.            }  
  46.         }  
  47.      }  
  48. }  

[cpp] view plaincopy

  1. #define MAXN 1010  
  2. #define INF 0xFFFFFFF  
  3. int  value[MAXN][MAXN];/*保存的是边权值*/  
  4. int  dis[MAXN];/*保存源点到任意点之间的最短路*/  
  5. int  father[MAXN];/*保存i点的父亲节点*/  
  6. int  vis[MAXN];/*记录顶点是否没取过*/   
  7.   
  8. void input(){       
  9.       int star , end , v;  
  10.       scanf("%d%d" , &n , &m);  
  11.       /*初始化value数组*/  
  12.      for(int i = 1 ; i <= n ; i++){  
  13.          for(int j = 1; j <= n ; j++)  
  14.              value[i][j] = INF;  
  15.      }  
  16.     for(int i = 0 ; i < m ; i++){  
  17.         scanf("%d%d%d" ,  &star , &end , &v);  
  18.         if(value[star][end] == INF)  
  19.             value[star][end] = value[end][star] = v;/*处理成无向图*/  
  20.         else{  
  21.             if(v < value[star][end])/*判断重边是否出现*/  
  22.                  value[star][end] = value[end][star] = v;  
  23.         }  
  24. }  
  25.   
  26. void dijkstra(int s){  
  27.      memset(vis , 0 , sizeof(vis));  
  28.      memset(father , 0 , sizeof(father));  
  29.      /*初始化dis数组*/  
  30.      for(int i = 1 ; i<= n ; i++)  
  31.           dis[i] = INF;  
  32.      dis[s] = 0;  
  33.      for(int i = 1 ; i <= n ; i++){/*枚举n个顶点*/  
  34.         int pos;  
  35.         pos = -1;  
  36.         for(int j = 1 ; j <= n ;j++){/*找到未加入集合的最短路点*/  
  37.            if(!vis[j] && (pos == -1 || dis[j] < dis[pos]))  
  38.               pos = j;  
  39.         }  
  40.         vis[pos] = 1;/*把这个点加入最短路径集合*/  
  41.         for(int j = 1 ; j <= n ; j++){/*更新dis数组*/  
  42.            if(!vis[j] && (dis[j] > dis[pos] + value[pos][j])){  
  43.              dis[j] = dis[pos] + value[pos][j];  
  44.              father[j] = pos;  
  45.            }  
  46.         }  
  47.      }  
  48. }  

 

[cpp] view plaincopy

  1. 优化过的,时间复杂度为o(mlogn);  
  2. /*利用邻接表来优化*/  
  3. #include<utility>    
  4. typedef pair<int , int>pii;/*pair专门把两个类型捆绑在一起的*/  
  5. priority_queue<pii,vector<pii>,greater<pii> >q;/*优先队列默认使用“<”,那么优先队列的元素是从大到小,所以自己定义“>”比较,STL中可以用greater<int>来表示">",这样就可以来声明一个小整数先出队的优先队列*/  
  6. #define MAXN 1010   
  7. #define INF 0xFFFFFFF   
  8. int n , m;/*有n个点,m条边*/  
  9. int first[MAXN] , next[MAXN];/*first数组保存的是节点i的第一条边,next保存的是边e的下一条边*/  
  10. int u[MAXN] , v[MAXN] , value[MAXN];  
  11. int vis[MAXN];  
  12. int dis[MAXN];  
  13.   
  14. /*读入这个图*/  
  15. void input(){  
  16.      scanf("%d%d" , &n , &m);  
  17.      /*初始化表头*/  
  18.      for(int i = 1 ; i <= n ; i++)  
  19.         first[i] = -1;  
  20.      for(int i = 1 ; i <= m ; i++){  
  21.         scanf("%d%d" , &u[i] , &v[i] , &value[i]);         
  22.         next[i] = first[u[i]];/*表头往后移动*/  
  23.         first[u[i]] = i;/*更新表头*/  
  24.      }  
  25. }  
  26.   
  27. /*Dijkstra*/  
  28. void Dijkstra(int s){  
  29.      memset(vis , 0 , sizeof(vis));  
  30.      /*初始化点的距离*/  
  31.      for(int i = 1 ; i <= n ; i++)  
  32.           dis[i] = INF;  
  33.     dis[s] = 0;  
  34.      while(!q.empty())  
  35.         q.pop();  
  36.      q.push(make_pair(dis[s] , s));  
  37.      while(!q.empty()){  
  38.           pii u = q.top();  
  39.           q.pop();  
  40.           int x = u.second;  
  41.           if(vis[x])  
  42.             continue;   
  43.           vis[x] = 1;  
  44.           for(int i = first[x] ; i != -1 ; i = next[i]){  
  45.              if(dis[v[e]] > dis[x] + value[i]){  
  46.                 dis[v[i]] = dis[x] + value[i];  
  47.                 q.push(make_pair(dis[v[i] , v[i]));  
  48.              }  
  49.           }  
  50.      }  
  51. }  

[cpp] view plaincopy

  1. 优化过的,时间复杂度为o(mlogn);  
  2. /*利用邻接表来优化*/  
  3. #include<utility>   
  4. typedef pair<int , int>pii;/*pair专门把两个类型捆绑在一起的*/  
  5. priority_queue<pii,vector<pii>,greater<pii> >q;/*优先队列默认使用“<”,那么优先队列的元素是从大到小,所以自己定义“>”比较,STL中可以用greater<int>来表示">",这样就可以来声明一个小整数先出队的优先队列*/  
  6. #define MAXN 1010  
  7. #define INF 0xFFFFFFF  
  8. int n , m;/*有n个点,m条边*/  
  9. int first[MAXN] , next[MAXN];/*first数组保存的是节点i的第一条边,next保存的是边e的下一条边*/  
  10. int u[MAXN] , v[MAXN] , value[MAXN];  
  11. int vis[MAXN];  
  12. int dis[MAXN];  
  13.   
  14. /*读入这个图*/  
  15. void input(){  
  16.      scanf("%d%d" , &n , &m);  
  17.      /*初始化表头*/  
  18.      for(int i = 1 ; i <= n ; i++)  
  19.         first[i] = -1;  
  20.      for(int i = 1 ; i <= m ; i++){  
  21.         scanf("%d%d" , &u[i] , &v[i] , &value[i]);         
  22.         next[i] = first[u[i]];/*表头往后移动*/  
  23.         first[u[i]] = i;/*更新表头*/  
  24.      }  
  25. }  
  26.   
  27. /*Dijkstra*/  
  28. void Dijkstra(int s){  
  29.      memset(vis , 0 , sizeof(vis));  
  30.      /*初始化点的距离*/  
  31.      for(int i = 1 ; i <= n ; i++)  
  32.           dis[i] = INF;  
  33.     dis[s] = 0;  
  34.      while(!q.empty())  
  35.         q.pop();  
  36.      q.push(make_pair(dis[s] , s));  
  37.      while(!q.empty()){  
  38.           pii u = q.top();  
  39.           q.pop();  
  40.           int x = u.second;  
  41.           if(vis[x])  
  42.             continue;   
  43.           vis[x] = 1;  
  44.           for(int i = first[x] ; i != -1 ; i = next[i]){  
  45.              if(dis[v[e]] > dis[x] + value[i]){  
  46.                 dis[v[i]] = dis[x] + value[i];  
  47.                 q.push(make_pair(dis[v[i] , v[i]));  
  48.              }  
  49.           }  
  50.      }  
  51. }  

 

 

 

floyd(权值非负)适用于有向图和无向图

1 floyd 的思想就是通过枚举n个点利用DP的思想来更新最短距离的,假设当前枚举到第k个点,那么就有任意的两个点i , j ,如果i k 相连 j k 相连 那么就可以知道这个时候dis[i][j] = min(dis[i][j] , dis[i][k] + dis[k][j]);,那么只要枚举完n个点,那么就说明已经完全更新完所有两点直间的最短路。

2 floyd算法是最简单的最短路径的算法,可以计算图中任意两点间的最短路径。floyd算法的时间复杂度为o(n^3),如果是一个没有边权的图,把相连的两点间的距离设为dis[i][j]=1.不相连的两点设为无穷大,用floyd算法可以判断i j两点是否相连。
3 floyd 算法不允许所有的权值为负的回路。可以求出任意两点之间的最短距离。处理的是无向图
4 缺点是时间复杂度比较高,不适合计算大量数据

5 如果dis[i][i] != 0,说明此时存在环。 

6 如果利用floyd求最小值的时候,初始化dis为INF , 如果是求最大值的话初始化为-1.

7 模板:

 

[cpp] view plaincopy

  1. #define INF 0xFFFFFFF   
  2. #define MAXN 1010   
  3. int dis[MAXN][MAXN];  
  4.   
  5. /*如果是求最小值的话,初始化为INF即可*/  
  6. void init(){  
  7.      for(int i = 1 ; i <= n ; i++){  
  8.         for(int j = 1 ; j <= n ; j++)  
  9.              dis[i][j] = INF;  
  10.         dis[i][i] = 0;  
  11.      }  
  12. }  
  13.   
  14. /*如果是求最大值的话,初始化为-1*/  
  15. void init(){  
  16.      for(int i = 1 ; i <= n ; i++){  
  17.         for(int j = 1 ; j <= n ; j++)  
  18.              dis[i][j] = -1;  
  19.      }  
  20. }  
  21.   
  22. /*floyd算法*/  
  23. void folyd(){  
  24.         for(int k = 1 ; k <= n ; k++){/*枚举n个点来更新dis*/  
  25.             for(int i = 1 ; i <= n ; i++){  
  26.                 for(int j = 1 ; j <= n ; j++)  
  27.                   if(dis[i][k] != -1 && dis[j][k] != -1)/*如果在求最大值的时候加上这一句*/  
  28.                      dis[i][j] = min(dis[i][k]+dis[k][j] , dis[i][j]);   
  29.             }   
  30.        }  
  31.  }  
  32.    

[cpp] view plaincopy

  1. #define INF 0xFFFFFFF  
  2. #define MAXN 1010  
  3. int dis[MAXN][MAXN];  
  4.   
  5. /*如果是求最小值的话,初始化为INF即可*/  
  6. void init(){  
  7.      for(int i = 1 ; i <= n ; i++){  
  8.         for(int j = 1 ; j <= n ; j++)  
  9.              dis[i][j] = INF;  
  10.         dis[i][i] = 0;  
  11.      }  
  12. }  
  13.   
  14. /*如果是求最大值的话,初始化为-1*/  
  15. void init(){  
  16.      for(int i = 1 ; i <= n ; i++){  
  17.         for(int j = 1 ; j <= n ; j++)  
  18.              dis[i][j] = -1;  
  19.      }  
  20. }  
  21.   
  22. /*floyd算法*/  
  23. void folyd(){  
  24.         for(int k = 1 ; k <= n ; k++){/*枚举n个点来更新dis*/  
  25.             for(int i = 1 ; i <= n ; i++){  
  26.                 for(int j = 1 ; j <= n ; j++)  
  27.                   if(dis[i][k] != -1 && dis[j][k] != -1)/*如果在求最大值的时候加上这一句*/  
  28.                      dis[i][j] = min(dis[i][k]+dis[k][j] , dis[i][j]);   
  29.             }   
  30.        }  
  31.  }  
  32.    


floyd扩展:

如何用floyd找出最短路径所行经的点: 1 这里要用到另一个矩阵P,它的定义是这样的:p(ij)的值如果为p,就表示i到j的最短行经为i->p...->j,也就是说p是i到j的最短行径中的j之前的第1个点。

2 P矩阵的初值为p(ij) = j。有了这个矩阵之后,要找最短路径就轻而易举了。对于i到j而言找出p(ij),令为p,就知道了路径i->p....->j;再去找p(pj),如果值为q,p到j的最短路径为p->q...->j;再去找p(qj),如果值为r,i到q的最短路径为q>r...->q;所以一再反复,就会得到答案。

3  但是,如何动态的回填P矩阵的值呢?回想一下,当d(ij)>d(ik)+d(kj)时,就要让i到j的最短路径改为走i->...->k->...->j这一条路,但是d(ik)的值是已知的,换句话说,就是i->...->k这条路是已知的,所以i->...->k这条路上k的第一个城市(即p(ik))也是已知的,当然,因为要改走i->...->k->...->j这一条路,p(ij)的第一个城市正好是p(ik)。所以一旦发现d(ij)>d(ik)+d(kj),就把p(ik)存入p(ij).

4 代码:

 

 

[cpp] view plaincopy

  1. int dis[MAXN][MAXN];  
  2. int path[MAXN][MAXN];  
  3.   
  4. void floyd(){  
  5.       int  i, j, k;  
  6.       /*先初始化化为j*/  
  7.       for (i = 1; i <= n; i++){  
  8.            for (j = 1; j <= n; j++)  
  9.                path[i][j] = j;  
  10.       }  
  11.       for (k = 1; k <= n; k++){/*枚举n个点*/  
  12.           for (i = 1; i <= n; i++){  
  13.               for (j = 1; j <= n; j++){  
  14.                    if (dis[i][j] > dis[i][k]+dis[k][j]){  
  15.                          path[i][j] = path[i][k];/*更新为path[i][k]*/  
  16.                          dis[i][j] = dis[i][k]+dis[k][j];  
  17.                     }  
  18.               }  
  19.            }  
  20.       }  
  21. }  

[cpp] view plaincopy

  1. int dis[MAXN][MAXN];  
  2. int path[MAXN][MAXN];  
  3.   
  4. void floyd(){  
  5.       int  i, j, k;  
  6.       /*先初始化化为j*/  
  7.       for (i = 1; i <= n; i++){  
  8.            for (j = 1; j <= n; j++)  
  9.                path[i][j] = j;  
  10.       }  
  11.       for (k = 1; k <= n; k++){/*枚举n个点*/  
  12.           for (i = 1; i <= n; i++){  
  13.               for (j = 1; j <= n; j++){  
  14.                    if (dis[i][j] > dis[i][k]+dis[k][j]){  
  15.                          path[i][j] = path[i][k];/*更新为path[i][k]*/  
  16.                          dis[i][j] = dis[i][k]+dis[k][j];  
  17.                     }  
  18.               }  
  19.            }  
  20.       }  
  21. }  


2  floyd求解环中的最小环

 

 

 

1 为什么要在更新最短路之前求最小环:
在第k层循环,我们要找的是最大结点为k的环,而此时Dist数组存放的是k-1层循环结束时的经过k-1结点的最短路径,也就是说以上求出的最短路是不经过k点的,这就刚好符合我们的要求。为什么呢?假设环中结点i,j是与k直接相连,如果先求出经过k的最短路,那么会有这样一种情况,即:i到j的最短路经过k。这样的话就形成不了环 。

2最小环改进算法的证明:
一个环中的最大结点为k(编号最大),与他相连的两个点为i,j,这个环的最短长度为g[i][k]+g[k][j]+dis[i][j] (i到j的路径中,所有结点编号都小于k的最短路径长度)。根据floyd的原理,在最外层循环做了k-1次之后,dist[i][j]则代表了i到j的路径中,所有结点编号都小于k的最短路径, 综上所述,该算法一定能找到图中最小环。

3 为什么还要value数组:
因为dis数组时刻都在变动不能表示出原来两个点之间的距离。

4 形成环至少要有3点不同的点,两个点是不能算环的。
5 代码:

 

[cpp] view plaincopy

  1. int mincircle = INF;  
  2. int dis[MAXN][MAXN];  
  3. int value[MAXN][MAXN];  
  4.   
  5. void floyd(){  
  6.      memcpy(value , dis , sizeof(value));  
  7.      for(int k = 1 ; k <= n ; k++){  
  8.           /*求最小环,不包含第k个点*/  
  9.           for(int i = 1 ; i < k ; i++){/*到k-1即可*/  
  10.                for(int j = i+1 ; j < k ; j++)/*到k-1即可*/  
  11.                    mincircle = min(mincircle , dis[i][j]+value[i][k]+value[k][j]);/*无向图*/  
  12.                    mincircle = min(mincircle , dis[i][j] +value[i][k]+value[k][j]);/*表示i->k , k->j有边*/  
  13.            }  
  14.           /*更新最短路*/  
  15.           for(int i = 1 ; i <= n ; i++){  
  16.                for(int j = 1 ; j <= n ; j++)  
  17.                    dis[i][j] = min(dis[i][k]+dis[k][j] , dis[i][j]);  
  18.           }  
  19.      }    
  20. }  

[cpp] view plaincopy

  1. int mincircle = INF;  
  2. int dis[MAXN][MAXN];  
  3. int value[MAXN][MAXN];  
  4.   
  5. void floyd(){  
  6.      memcpy(value , dis , sizeof(value));  
  7.      for(int k = 1 ; k <= n ; k++){  
  8.           /*求最小环,不包含第k个点*/  
  9.           for(int i = 1 ; i < k ; i++){/*到k-1即可*/  
  10.                for(int j = i+1 ; j < k ; j++)/*到k-1即可*/  
  11.                    mincircle = min(mincircle , dis[i][j]+value[i][k]+value[k][j]);/*无向图*/  
  12.                    mincircle = min(mincircle , dis[i][j] +value[i][k]+value[k][j]);/*表示i->k , k->j有边*/  
  13.            }  
  14.           /*更新最短路*/  
  15.           for(int i = 1 ; i <= n ; i++){  
  16.                for(int j = 1 ; j <= n ; j++)  
  17.                    dis[i][j] = min(dis[i][k]+dis[k][j] , dis[i][j]);  
  18.           }  
  19.      }    
  20. }  

 

Bellman_Ford(权值可正可负),用来判断负环 

1 Bellman_Frod可以计算边权为负值的最短路问题,适用于有向图和无向图.用来求解源点到达任意点的最短路。

2 在边权可正可负的图中,环有零环,正环,负环3种。如果包含零环和正环的话,去掉以后路径不会变成,如果包含负环则最短路是不存在的。那么既然不包含负环,所以最短路除了源点意外最多只经过n-1个点,这样就可以通过n-1次的松弛得到源点到每个点的最短路径。

3 时间复杂度o(n*m);
4 如果存在环的话就是经过n-1次松弛操作后还能更新dis数组。
5 模板:

 

[cpp] view plaincopy

  1. /* 
  2. 适用条件: 
  3. 1单源最短路径 
  4. 2有向图和无向图 
  5. 3边权可正可负 
  6. */  
  7.   
  8. #define INF 0xFFFFFFF   
  9. #define MAXN 1010*2   
  10. int dis[MAXN];/*dis[i]表示的是源点到点i的最短路*/  
  11. strucu Edge{  
  12.    int x;  
  13.    int y;  
  14.    int value;  
  15. }e[MAXN];  
  16.   
  17. /*返回最小值*/  
  18. int min(int a , int b){  
  19.     return a < b ? a : b;  
  20. }  
  21.   
  22. /*处理成无向图*/  
  23. void input(){  
  24.      for(int i = 0 ; i < m ; i++){  
  25.         scanf("%d%d%d" , e[i].x , &e[i].y , &e[i].value);  
  26.         e[i+m].x = e[i].y;/*注意地方*/  
  27.         e[i+m].y = e[i].x;/*注意地方*/  
  28.         e[i+m].value = e[i].value;            
  29.      }  
  30. }  
  31.   
  32. /*假设现在有n个点,m条边*/  
  33. void Bellman_Ford(int s){  
  34.     /*初始化dis数组*/  
  35.     for(int i = 1 ; i <= s ; i++)  
  36.          dis[i] = INF;  
  37.     dis[s] = 0;  
  38.     for(int i = 1 ; i < n ; i++){/*做n-1次松弛*/  
  39.        for(int j = 0 ; j < 2*m ; j++){/*每一次枚举2*m条边,因为是无向图*/  
  40.           if(dis[e[j].y] > dis[e[j].x] + e[j].value)  
  41.            dis[e[j.].y] = dis[e[i].x]+e[j].value;/*更新dis[e[j].y]*/  
  42.           }  
  43.        }  
  44.     }  
  45. }  

[cpp] view plaincopy

  1. /* 
  2. 适用条件: 
  3. 1单源最短路径 
  4. 2有向图和无向图 
  5. 3边权可正可负 
  6. */  
  7.   
  8. #define INF 0xFFFFFFF  
  9. #define MAXN 1010*2  
  10. int dis[MAXN];/*dis[i]表示的是源点到点i的最短路*/  
  11. strucu Edge{  
  12.    int x;  
  13.    int y;  
  14.    int value;  
  15. }e[MAXN];  
  16.   
  17. /*返回最小值*/  
  18. int min(int a , int b){  
  19.     return a < b ? a : b;  
  20. }  
  21.   
  22. /*处理成无向图*/  
  23. void input(){  
  24.      for(int i = 0 ; i < m ; i++){  
  25.         scanf("%d%d%d" , e[i].x , &e[i].y , &e[i].value);  
  26.         e[i+m].x = e[i].y;/*注意地方*/  
  27.         e[i+m].y = e[i].x;/*注意地方*/  
  28.         e[i+m].value = e[i].value;            
  29.      }  
  30. }  
  31.   
  32. /*假设现在有n个点,m条边*/  
  33. void Bellman_Ford(int s){  
  34.     /*初始化dis数组*/  
  35.     for(int i = 1 ; i <= s ; i++)  
  36.          dis[i] = INF;  
  37.     dis[s] = 0;  
  38.     for(int i = 1 ; i < n ; i++){/*做n-1次松弛*/  
  39.        for(int j = 0 ; j < 2*m ; j++){/*每一次枚举2*m条边,因为是无向图*/  
  40.           if(dis[e[j].y] > dis[e[j].x] + e[j].value)  
  41.            dis[e[j.].y] = dis[e[i].x]+e[j].value;/*更新dis[e[j].y]*/  
  42.           }  
  43.        }  
  44.     }  
  45. }  

 

 

 

SPFA(权值可正可负),判断负环.
1用来求解单源最短路径,源点到任意点的最短路。
2 算法介绍:建立一个队列q,初始时队列里只有一个起始点,在建立一个数组dis记录起始点到所有点的最短路径,并且初始化这个数组。然后进行松弛操作,用 队列里面的点去刷新起始点到所有点的最短路,如果刷新成功且刷新点不再队列中则把该点加入到队列最后,重复执行直到队列为空。
3 时间复杂度:O(ke),k指的是所有顶点的进队的平均次数,可以证明k<=2,e为边数

4 可以用SPFA来存在是否存在环,如果是的话就是存在一条边的松弛操作大于等于n。
5 模板:

 

[cpp] view plaincopy

  1. /* 
  2. 1 n个点 m条边 
  3. 2 邻接表存储图: first[i]存储的是节点i的第一条边的编号,nest[i]存储的是编号为i的边的下一条边的编号。 
  4. 3 star[i]表示编号为i的边的起点,end[i]表示编号为i的边的终点,value[i]表示编号为i的边的权值。 
  5. 4 dis[i] 表示的源点到i的最短路 
  6. */  
  7.   
  8. #define MAXN 1010   
  9. #define INF 0xFFFFFFF   
  10.   
  11. int n , m;  
  12. int first[MAXN] , next[MAXN];  
  13. int star[MAXN] , end[MAXN] , value[MAXN];  
  14. int dis[MAXN];  
  15. queue<int>q;  
  16.   
  17. /*输入*/  
  18. void input(){  
  19.      scanf("%d%d" , &n , &m);  
  20.      /*初始化表头*/  
  21.      for(int i = 1 ; i <= n ; i++){  
  22.         first[i] = -1;  
  23.         next[i] = -1;  
  24.      }  
  25.      /*读入m条边*/  
  26.      for(int i = 0 ; i < m ; i++){  
  27.         scanf("%d%d%d" , &star[i] , &end[i] , &value[i]);  
  28.         star[i+m] = end[i];  
  29.         end[i+m] = star[i];  
  30.         value[i+m] = value[i];  
  31.   
  32.         next[i] = first[star[i]];/*由于要插入表头,所以将原先表头后移*/  
  33.         first[star[i]] = i;/*插入表头*/  
  34.         next[i+m] = first[star[i+m]];  
  35.         first[star[i+m]] = i+m;  
  36.      }  
  37. }  
  38.   
  39. /*SPFA*/  
  40. void SPFA(int s){  
  41.      while(!q.empty())  
  42.           q.pop();  
  43.      int vis[MAXN];  
  44.      memset(vis , 0 , sizeof(vis));  
  45.      /*初始化dis*/  
  46.      for(int i = 1 ; i <= n ; i++)  
  47.           dis[i] = INF;  
  48.      dis[s] = 0;  
  49.      q.push(s);/*将源点加入队列*/  
  50.      vis[s] = 1;/*源点标记为1*/  
  51.      while(!q.empty()){  
  52.           int x = q.front();  
  53.           q.pop();  
  54.           vis[x] = 0;/*注意这里要重新标记为0,说明已经出队*/  
  55.           /*枚举和点x有关的所有边*/  
  56.           for(int i = first[x] ; i != -1 ; i = next[i]){  
  57.              if(dis[end[i]] > dis[x] + value[i]){/*松弛操作,利用三角不等式*/  
  58.                dis[end[i]] = dis[x] + value[i];  
  59.                if(!vis[end[i]]){/*如果该点不再队列里面*/  
  60.                   vis[end[i]] = 1;                  
  61.                   q.push(end[i]);  
  62.                }  
  63.              }  
  64.           }  
  65.      }  

[cpp] view plaincopy

  1. /* 
  2. 1 n个点 m条边 
  3. 2 邻接表存储图: first[i]存储的是节点i的第一条边的编号,nest[i]存储的是编号为i的边的下一条边的编号。 
  4. 3 star[i]表示编号为i的边的起点,end[i]表示编号为i的边的终点,value[i]表示编号为i的边的权值。 
  5. 4 dis[i] 表示的源点到i的最短路 
  6. */  
  7.   
  8. #define MAXN 1010  
  9. #define INF 0xFFFFFFF  
  10.   
  11. int n , m;  
  12. int first[MAXN] , next[MAXN];  
  13. int star[MAXN] , end[MAXN] , value[MAXN];  
  14. int dis[MAXN];  
  15. queue<int>q;  
  16.   
  17. /*输入*/  
  18. void input(){  
  19.      scanf("%d%d" , &n , &m);  
  20.      /*初始化表头*/  
  21.      for(int i = 1 ; i <= n ; i++){  
  22.         first[i] = -1;  
  23.         next[i] = -1;  
  24.      }  
  25.      /*读入m条边*/  
  26.      for(int i = 0 ; i < m ; i++){  
  27.         scanf("%d%d%d" , &star[i] , &end[i] , &value[i]);  
  28.         star[i+m] = end[i];  
  29.         end[i+m] = star[i];  
  30.         value[i+m] = value[i];  
  31.   
  32.         next[i] = first[star[i]];/*由于要插入表头,所以将原先表头后移*/  
  33.         first[star[i]] = i;/*插入表头*/  
  34.         next[i+m] = first[star[i+m]];  
  35.         first[star[i+m]] = i+m;  
  36.      }  
  37. }  
  38.   
  39. /*SPFA*/  
  40. void SPFA(int s){  
  41.      while(!q.empty())  
  42.           q.pop();  
  43.      int vis[MAXN];  
  44.      memset(vis , 0 , sizeof(vis));  
  45.      /*初始化dis*/  
  46.      for(int i = 1 ; i <= n ; i++)  
  47.           dis[i] = INF;  
  48.      dis[s] = 0;  
  49.      q.push(s);/*将源点加入队列*/  
  50.      vis[s] = 1;/*源点标记为1*/  
  51.      while(!q.empty()){  
  52.           int x = q.front();  
  53.           q.pop();  
  54.           vis[x] = 0;/*注意这里要重新标记为0,说明已经出队*/  
  55.           /*枚举和点x有关的所有边*/  
  56.           for(int i = first[x] ; i != -1 ; i = next[i]){  
  57.              if(dis[end[i]] > dis[x] + value[i]){/*松弛操作,利用三角不等式*/  
  58.                dis[end[i]] = dis[x] + value[i];  
  59.                if(!vis[end[i]]){/*如果该点不再队列里面*/  
  60.                   vis[end[i]] = 1;                  
  61.                   q.push(end[i]);  
  62.                }  
  63.              }  
  64.           }  
  65.      }  
多源最短路径Floyd算法(可用于找负回路) C++实现 概述 Dijkstra算法是经典的求单源最短路径算法,当有以下需求时: 要求出任意两点间的最短路径; 可能有负权边; 用Floyd算法,可以在不存在负回路时, 算法思想 采用动态规划法, ... 阅读详情

相关推荐

判断弗洛伊德/FLOYD算法是不是有负环的

纯属个人看书后的想法,哪有不对请多多指点 首先模拟floyd求最短路径的过程,截取其中为环的部分,假设进入环时距离0(初始位置)的距离为5,然后访问顺序分别为1 2 3 4距离为1 2 3 -8如图 首先距离1节点距离为5然后5+1距离二为6,距离3为6+2为8,然后4对应11,经过三圈循环之后他们分别对应的值如上。 最终结果为1 2 3 4分别对应1 2 4 7,然后我们观察这4个

L_x_4的博客 6381

最短路算法

最短路径问题旨在寻找图中两节点之间的最短路径,常用的算法有以下四种。注意是把图处理成无向还是有向Dijkstra's (权值非负) 1 Dijkstra's算法解决的是图中单个源点到其它顶点的最短路径。只能解决权值非负 2 Dijkstral只能求出任意点到达源点的最短距离(不能求出任意两点之间的最短距离),同时适用于有向图和无向图,复杂度为O(n^2). 3算法的过程: 1设置顶点集合...

我是传奇 306

浅说最短路

我们在信息学奥赛中,时常会遇到让我们求图上最短路的问题,之前我们可以敲dfs或bfs,但是这两个一个时间复杂度太大了,一个有限制条件,所以说我们还不如重新研究一个算法,所以这就有了最短路算法。 但是这里有个点值得注意,最短路算法不仅仅可以用于解决最短路,还可以用于解决一些不等式(组)求解的问题,也就是我们经常说的差分约束。友情提示:在学习这篇之前,请先学习图论基础章如果说,我们只想求一个点到另一个点或者说一个点到其他所有点的最短路的话,这也就是在求单源最短路,一般情况下,单源最短路会用两种算法解决,一个是D

CylMK的博客 944

最短路径问题相关算法、原理及适用场景

比较有效的算法之一是马丁斯(Martins)在1999年提出的MPS算法,其特点是简化了偏离路径的长度计算,在生成候选边时不像Yen算法那样计算每条候选路径的长度,而是要求更新每条弧上的减少长度,只选择长度减少最小的弧作为最短偏离路径,该算法在一般情况下可以提高运行速度,但是在最差的情况下与Yen算法的时间复杂度一样。Dijkstra算法和Floyd算法均为动态规划算法且是一种贪心算法,即进行无方向性的搜索,每一步转移都由计算机选择当前的最优解并生成新的状态,一直到达目标状态为止。

博客简介 4245

最短路问题(五个算法模板)

题目给定一个有向图,图中有 𝑛n 个点和 𝑚m 条边。图中可能存在重边和自环,所有边权均为正值。请你求出从 1 号点到 𝑛n 号点的最短距离。如果无法从 1 号点走到 𝑛n 号点,则输出 -1。

2401_87934559的博客 2587

【图论算法】 最短路,次短路,k短路总结

在图论里,最短路,次短路,k短路的问题很常见。 这里总结一下。 存图技巧 数据小,稠密图的一般用邻接矩阵 稀疏图,数据大一般用邻接表(vector,链式前向星都可) 邻接矩阵 const int maxn = 1e5+5; int Graph[maxn][maxn]; // 正权图可以初始化成-1来判断是否连通,负权图可以再考虑开个数组或者用一个很大的值。 链式前向星 const int max...

一个蒟蒻的博客 1996

专题·最短路【including Dijkstra, SPFA,Floyd,传递闭包,二维最短路,分层图最短路,最短路计数……

DIj算法,堆优化版本,线段树优化版本; SPFA算法,Floyd算法,传递闭包; 如标题的各种最短路的应用

樱狸✨愿携清风归来处 1万+

二次开发vba_CATIA VBA(VBS)二次开发:使用Search批量选择元素

在CATIA二次开发中很多在程序中进行自动交互的方法或函数都需要使用选择集作为参数,将几何元素按照要求批量添加到选择集中也是实现程序自动运行的有效方法。在前面的文章《CATIA使用VBA(VBS)二次开发时用户的交互选择》和《CATIA使用VBA(VBS)二次开发时工程图和草图位置的交互选择函数Indicate2D》中介绍了在CATIA VBA(VBS)二次开发中用户和选择集之间的交互操...

weixin_32497403的博客 1321

最短路问题——单源最短路

是的,所以我们上面也说了: Bellman-Ford算法是比较暴力的把所有的边都更新(即先后对所有的顶点的相邻顶点进行松弛),而不像Dijkstra算法的贪心那样每次选的都是最短的,也因此它一遍过后可能得不出最短的路径,可能需要进行多次迭代。

2301_80224556的博客 1554

学习海康VisionMaster之表面缺陷滤波

本文介绍了VisionMaster中表面缺陷滤波技术的应用。该技术通过数学变换抑制背景干扰、增强缺陷特征,适用于电池铝壳、垫圈/螺丝等无纹理背景的表面缺陷检测(划痕、凹坑、异物等)。操作流程包括:图像导入、轮廓定位、位置修正、参数设置(重点讲解滤波核尺寸/数量/标准差等关键参数的调整策略)。文章通过案例演示了如何通过多方向滤波响应识别表面划伤,并指出需结合blob分析进一步优化检测结果。该技术对工业质检具有实用价值,参数设置需结合缺陷特征与背景特性灵活调整。

yuhouxiyang的专栏 2826

Microapp 接入vite子应用

MicroApp接入vite版本,干货满满,手把手步骤说明,加上报错说明,赶紧上车!

outsider76557的博客 4658

最短路问题——多源最短路

当处理到第。

2301_80224556的博客 1576

超声信号处理——硬件电路中的混频应用

本文介绍了超声多普勒系统的信号处理原理。系统通过波形振荡器产生高频信号,经换能器转换为超声波发射,接收反射信号后与原始信号混频,利用三角函数的积化和差特性产生包含多普勒频移的低频差频信号和高频和频信号。通过低通滤波器滤除高频成分后,即可获得纯净的多普勒信号。这种处理方法将MHz级高频信号转换为可听低频信号,降低了系统复杂度与成本。数学推导表明,差频信号频率正好

fcxgfdjy的博客 1123

最短路问题(超详细~~)

文章目录最短路问题分类朴素Dijkstra算法 最短路问题分类 最短路算法知识结构图 注:n为顶点数,m为边数 每种不同的情况都有相应最适合的算法,但不用拘泥于一定要用某个算法。 单源最短路:求一个点到其他所有点的最短距离 多源汇最短路:源 指 起点,汇 指 终点。任意两点间的最短距离(起点、终点不确定) 稠密图:m至少和n^2大致是一个级别 (稠密图用邻接矩阵存储) 稀疏图:m至少和n大致是一个级别 (稀疏图用邻接表存储) 重点:建图,如何把原问题抽象成一个最短路问题,如何定义点和边。 朴素Di

灯火阑珊_ 8730

16QAM调制解调仿真(matlab,详细介绍仿真方案的设计、结果及结论、完整代码及注释)

16QAM调制解调仿真目录一、仿真要求二、仿真方案详细设计三、仿真结果及结论四、仿真代码 一、仿真要求 1.用基带等效的方式仿真16-QAM在AWGN信道下的误码率和误比特率性能,并与理论值相比较; 2.高阶与低阶的性能比较。 二、仿真方案详细设计 三、仿真结果及结论 仿真结果 16QAM的星座点图 64QAM的星座点图 16QAM加噪声后的星座点图 64QAM加噪声后的星座点图 16-QAM载波调制信号在AWGN信道下的误比特率性能比较 结论:由图可知,16QAM的误符号率

mango 5万+

Silvaco光电探测学习笔记(一)——有关响应和暗电流

习惯用md记笔记,索性发出来,一是为了在线同步,二是希望能帮到需要的人。

qq_41584406的博客 8012

【算法】图论——单源最短路问题

邻接矩阵存储图判断一个顶点是否已经确定最短路的数组从起点到第i个点的距离数组。距离数组中可能暂时存储的不是最短路,具体看上面的判断数组题目链接:邻接表边的权值表距离表判断表,用于判断该顶点是否遍历过堆,使用STL中的priority_queueedges[M]:用于存储所有边,M为边的数量dis[N]:用于存储经过一次松弛操作后的顶点距离backup[N]:dis的拷贝为什么要有backup?

m0_73904148的博客 1934

PCB压合原理与工艺全流程深度解析

PCB压合是多层印制电路板制造中的核心工序,其本质并非简单物理叠加,而是高分子树脂流动、玻璃布应力释放、铜箔热膨胀及界面能调控的协同过程。理解压合原理,需掌握温度-压力-时间三维曲线动态关系;优化工艺流程,须兼顾叠板精度、热压参数匹配与冷却策略;关键影响因素如半固化片(PP)选型、铜箔表面处理、设备温场均匀性、结构对称性、环境湿度及操作手法,共同决定层间结合力、翘曲度与孔壁质量。本文围绕PCB压合原理、工艺流程、关键影响因素三大维度展开,融合IPC标准、实测数据与产线案例,为工艺工程师、NPI人员及设备维护

weixin_29191081的博客 253

第三章 图论 No.2单源最短路之虚拟源点,状压最短路与最短路次短路条数

而spfa的更新不具有拓扑序,即不存在最短路树,要是图中存在负权边,无法使用天然具有拓扑序的bfs和dijkstra时,只能先用spfa求出最短路,维护出最短路树,再求最短路条数。对于spfa,由于它是暴力算法的优化,每个点都会入队与出队多次,所以spfa的更新不具有拓扑序,已经出队(更新完成)的点可能影响被后续入队的点影响。对于BFS,由于每个点只会入队一次且只会出队一次,说明BFS的更新天然地具有拓扑序,因为出队的点不会被后续入队的点影响。这里涉及到二维坐标到一维的转换,然后用邻接表存储图。

凡事都是靠练习 3140

瑞萨RZN2L工业以太网开发避坑指南:EtherCAT从入门到通信调试全流程

本文详细解析了瑞萨RZN2L MPU在工业以太网开发中的EtherCAT从站配置与通信优化全流程。通过硬件设计关键点、协议栈选型、PDO映射策略及DC同步精度优化等实战技巧,帮助开发者快速搭建高效通信框架并解决调试中的常见问题,特别适合工业自动化领域的实时通信需求。

aitie1479的博客 461

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

MATLAB 最短路

本文介绍了 MATLAB 中的最短路问题,以及如何使用 MATLAB 解决最短路问题。

小嗷犬的博客 5205

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

图最短路问题

一、图的最短路问题分类 求解最短路问题有很多种解决方案,各个方案会有对应的解决类型 单源最短路问题:BFS用于解决单源无权最短路问题 Dijkstra算法用于解决单源正权最短路问题 Bellman-Ford、SPFA算法用于解决负权最短路问题 各顶点最短路问题:Floyd算法 二、BFS广度优先搜索 1、BFS按照到源点的最短距离将图中的各点分类,按照距离从小到大访问各点。为了实现按距离大小访问各...

qq_43575926的博客 891

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

上一篇: 博弈论
下一篇: 最大流
三生石1103
博客等级 码龄12年 16粉丝 87原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值