dfs,bfs,单源最短路,多源最短路(周报1)

   哦,要开始码字了,有点紧张,又有点兴奋,好啦,废话不多说,开始吧。

   1.dfs

    dfs,中文名称深度优先搜索,从顶点V开始,访问这个顶点,然后依次从V的未被访问的邻接点出发深度优先遍历图,直至图中所有和V有路径的相通的顶点都被访问了,如果此时还有顶点未被访问,则选择图中未被访问的那个顶点作为起点,重复上述动作。emmm,上面这句我直接超的。好吧,现在来解释一下把。(以下文字内容为本博主自己的见解,如果有误,请提醒我,不许指出哦)

    

    (图片来源:https://lemon2013.github.io/2017/05/27/graph-search/

    A.无向图(根据字母顺序选取结点)

    以A为初始点,记录点A为已访问,A的后续结点为B,E,选择结点B,记录点B为已访问,B的后续节点为C,D,E,选择结点C,记录点C为已访问结点,C的后续结点为D,选择结点D,记录结点D为已访问结点,D的后续节点为E,选择结点E,记录结点E为已访问结点,E无后续节点,回溯到点D,点D无后续结点,回溯到点C,点C无后续结点,回溯到B点,点B后续节点还有D,E,点D和点E皆为已访问结点,所以回溯到点A,点A后续结点还剩点E,点E已访问,所以dfs结束。

    B.有向图(根据字母顺序选取结点)

    以A为初始点,记录A已访问,A的后续节点为B,D,选择结点B,记录点B为已访问,B的后续节点为C,D,选择结点C,记录结点C为已访问结点,点C后续结点为E,选择结点E,记录结点E为已访问结点,结点E无后续节点,回溯到点C,点C无其他后续结点,回溯到点B,点B还有一个未访问后续节点为D,选择点D,记点D为已访问结点,点D后续节点均被访问,回溯到点B,点B无后续结点,回溯到点A,点A无后续结点,dfs结束。

    有向图和无向图的dfs都一个样,主要注意的是遍历的顺序和条件。

   2.bfs

    bfs,中文名称为广度优先搜索,它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较广的区域,故得名。不多说,上图!

     

    A.无向图

    以A为初始点,A进栈,记录点A为已访问,A出栈,A的相邻节点为B,E。 B,E入栈,记录结点B已访问,B相邻结点为C与D。B出栈,C,D入栈,E相邻结点以入栈,记录点E为已访问,E出栈,C相邻结点以入栈,记录C为已访问,C出栈,记录D为已访问,D出栈。

    A进栈--BE进栈--A出栈--CD进栈--B出栈--E出栈--C出栈--D出栈

    B.有向图

    以A为初始点,A进栈,记录点A为已访问,A的后续结点为B,D。BD入栈,记录B为已访问,B的后续结点为C,C进栈,B出栈,记录D为已访问,D的后续结点为E,E入栈,D出栈,记录点C为已访问,C出栈,记录点E位于服务,E出栈。

    A进栈--BD进栈--A出栈--C进栈--B出栈--E进栈--D出栈--C出栈--E出栈

  3.单源最短路

     单源最短路呢,意思就是从一个点到其他所有点的最短边权。

    (1)Dijkstra(其他的以后总结)

      Dijkstra算法采用贪心策略:按路径长度递增的顺序,逐个产生各顶点的最短路径。算法过程中需要维护一个顶点集,此顶点集保存已经找到最短路径的顶点。还需要维护一个距离数组dist, dist[i]表示第i个顶点与源结点s的距离长度。

     问题:求1到其余4点的最短路径值?(例题来源:https://blog.csdn.net/jiahui524/article/details/6636913)

       

       

      初始:S中只有1这个点,dist[2]~dst[5]中最短距离为10,最大为INF;

      第一次:选择最短距离的点2,加入S,更新1到其余点的距离,dist[3] = dist[2] + a[2][3] = 60;

      第二次:选择最短距离的点4,加入S,更新1到其余点的距离,dist[5] = dist[4] + a[4][5] = 90, dist[3] = dist[4] + a[4][3] = 50;

      第三次:选择最短距离的点3,加入S,更新1到其余点的距离,dist[5] = dist[3] + a[3][5] = 60;

      第四次:选择最短距离的点5,加入S,更新1到其余点的距离;

        

int dijkstra(int s,int t) {
 
       初始化S={空集}
 
       d[s] = 0; 其余d值为正无穷大
 
       while (NOT t  in S)
 
       {
 
              取出不在S中的最小的d[i];
 
              for (所有不在S中且与i相邻的点j)
 
                if (d[j] > d[i] + cost[i][j]) d[j] = d[i] + cost[i][j]; ( “松弛”操作” )
 
              S = S + {i}; //把i点添加到集合S里
 
       }
 
       return d[t];
 
}

代码实现:(1到5的最短路径(dist[5]))

#include <iostream> 
using namespace std; 
#define MAX 9999999 
#define LEN 210 
int map[LEN][LEN];    //某点到某点两点间的的距离 
int dist[LEN];              //记录当前点到源点的最短路径长度 
int mark[LEN];           //加入进来的点的集合 
//初始化map为正无穷大 
void init(){ 
       int i,j; 
       for(i=0;i<LEN;i++){ 
              for(j=0;j<LEN;j++){ 
                     map[i][j]=MAX; 
              } 
       } 
} 
//n:多少条路  start:起始点  
void myDijstra(int n,int start){ 
       int i,j,min,k; 
       for(i=1;i<=n;i++){ 
              mark[i]=0;//没有点加入 
              dist[i]=map[start][i];//初始 
       } 
       mark[start]=1;//把起始点加进来 
       dist[start]=0; 
       for(i=1;i<=n;i++){ 
              min=MAX; 
              for(j=1;j<=n;j++){ 
                     if(!mark[j] && dist[j]<min){    //取出不在mark里的最小的dist[i] 
                            min=dist[j]; 
                            k=j;//标记 
                     } 
              } 
              if(min==MAX) 
                     break; 
              mark[k]=1;//把K加进来 
              //做松弛操作 
              for(j=1;j<=n;j++){ 
                     if(!mark[j] && dist[j]>dist[k]+map[k][j]){ 
                            dist[j]=dist[k]+map[k][j]; 
                     } 
              } 
       } 
} 
int main(){ 
       int i,j,n,line; 
       int a,b,d; 
       cin>>n>>line;   //输入点和边 
       init(); 
       for(i=0;i<line;i++){ 
              cin>>a>>b>>d;  //输入各边的权值 
              if(map[a][b]>d){ 
                     map[a][b]=map[b][a]=d; 
              } 
       }
       myDijstra(n,1);//调用方法
 
       //输出1到5的最短路径
 
       cout<<dist[5]<<endl;
 
       return 0;
 
}

4.多源最短路

  (1)floyd

    多源最短路就是指每一个点到图中其他顶点的最短路。

    代码模板:

int g[N][N];
void floyd(int n) {
    for (int k = 1; k <= n; ++k) {
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
            }
        }
    }    
}

猜你喜欢

转载自www.cnblogs.com/cccyx/p/11503886.html