<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Kruscal算法求圖的最小生成樹

      Kruscal算法求圖的最小生成樹

      概述

      ? 和Prim算法求圖的最小生成樹一樣,Kruscal算法求最小生成樹也用到了貪心的思想,只不過前者是貪心地選擇點,后者是貪心地選擇邊。而且在算法的實現中,我們還用用到了并查集(也稱不相交集的)Union /Find 算法來判斷兩個節點連通后會不會形成一個環。該算法的思想很簡單:將圖的所有邊按從小到大順序排序,每次都選取權值最小的邊加入最小生成樹,如果該邊的加入會使生成樹形成一個環,則跳過該邊。
      ? 這里引入并查集的概念,可以使問題變得簡單化。并查集就是利用一個數組sets,如果sets[a]=b,那么我們說a和b在一個生成樹(集合)中,且a的雙親是b,如果sets[a]=a,那么我們說a是一個生成樹的根。一個圖的最小生成樹在還沒有完全生成前,可能存在多個互不連通的生成樹,他們是不相交的集合,我們需要把這些不同的生成樹連通起來。
      ?于是,通過定義一個findroot函數,我們可以找到某頂點的雙親,然后找到該頂點的雙親的雙親,最終找到頂點所在最小生成樹的根,例如:如果我們知道sets[a]=b,sets[b]=c,sets[c]=c,那我們可以說a、b、c在同一棵生成樹(集合)里,且所在最小生成樹的根為c。假設另一個不相交的生成樹的根為d,如果我們令sets[c]=d,則將這兩個生成樹合并為了一個大的生成樹,其根為d。

      算法圖解

      1.創建一個9條邊,6個頂點的帶權無向連通圖。
      圖的初始狀態
      初始狀態的并查集如下:
      在這里插入圖片描述
      2.將圖所有邊按權值進行排序。選擇權值最小的一條邊的兩個鄰點。為了避免混亂,統一約定該邊右邊的鄰點加入左邊的鄰點的并查集中,在圖中表示為2頂點掛在1頂點下面。
      在這里插入圖片描述
      在這里插入圖片描述
      3.就這樣,按照權值從小到大不斷遍歷所有邊,都統一把邊的大序號的鄰點加入小序號的鄰點所在的生成樹中,3頂點掛在2頂點下面,4頂點掛在3頂點下面,5頂點掛在4頂點下面,6頂點掛在2頂點的下面,最終最小生成樹不斷長大,且最后所有頂點本質上都掛在1頂點下面,即最小生成樹的根為1頂點。
      在這里插入圖片描述
      在這里插入圖片描述
      4.最好還剩4條邊沒有遍歷。但我們發現,這4條邊的兩個鄰點都在同一個生成樹中了,即他們findroot的結果都是1。如果我們把任意一條邊的兩個鄰點連接起來,都會形成一個環,這是不允許的。故最小生成樹的生成就此結束。

      代碼

      1.引入頭文件,和之前所講的的其他圖論算法不同的是,這里單獨定義一個表示圖的邊的類,用u,v記錄邊的鄰接點,w記錄邊的權值。

      #include<iostream>
      #include<vector>
      #include<algorithm>
       //這里同之前我們實現prim算法用的鄰接矩陣不同
       //我們用一直特殊的儲存方式儲存圖的邊
       using namespace std;
      
      struct edge{
          //邊的兩個鄰點,其中u編號小于v編號
          int u;
          int v;
          //邊的權值
          int w;
      };
      

      2.定義表示圖的類

      struct Graph{
          //儲存邊的容器
          vector<edge> edges;
          //定義并查集,記錄各頂點的“根”,確定各頂點是否在同一棵樹里
          vector<int> sets;
          //構造函數
          Graph(int vertexnum,int edgenum);
          //析構函數
          ~Graph();
          //kruascal算法的調用接口
          void kruscal();
          //尋根函數,后面會詳細講解其用途
          int findroot(int vertex);
          //按權值給圖的邊排序的函數
          void sortedges();
      };
      

      3.這里自定義一個排序比較函數,后面給儲存邊的容器排序時會用到。

      //排序自定義操作函數
      bool cmp(edge a,edge b){
          return a.w<=b.w;
      }
      

      4.Graph類的構造函數以及析構函數

      Graph::Graph(int vertexnum,int edgenum){
          edges.resize(edgenum+1);
          sets.resize(vertexnum+1);
          //初始化并查集。每個節點相互獨立,自己是自己所在生成樹的根
          for(int i=1;i<=vertexnum;i++){
              sets[i]=i;
          }
          cout<<"請依次輸入各邊的兩個頂點及其權值"<<endl;
          //注意,為了跟后面尋根函數配合,要保證u定點編號小于v頂點編號
          for(int i=1;i<=edgenum;i++){
              int a,b,w;
              cin>>a>>b>>w;
              if(a>b){
                  edges[i].u=a;
                  edges[i].v=b;
              }
              else{
                  edges[i].v=a;
                  edges[i].u=b;
              }
              edges[i].w=w;
          }
      }
      Graph:: ~Graph(){
          edges.clear();
          sets.clear();
      }
      

      5.Kruscal算法的實現。

       //kruascal算法的實現方法
      void Graph::kruscal(){
          //調用成員函數對圖的所有邊進行排序
          sortedges();
          int sum=0;
          for(int i=1;i<=edges.size()-1;i++){
              /*如果該邊的兩個頂點的根不相同,則讓u鄰接點成為v鄰接點的根的根。
              說形象一點,就是讓v鄰接點的BOSS歸順于u鄰接點的BOSS;
              從而讓v歸順于u的BOSS,
              并將該邊的權值加入總和中 */
              if(findroot(edges[i].u)!=findroot(edges[i].v)){
                  sets[findroot(edges[i].v)]=findroot(edges[i].u);
                  //此處非常容易錯,讀者寫代碼時一定要仔細
                  sum += edges[i].w;
              }
              //否則不進行任何操作
          }
          cout<<"最小生成樹的權值和為:"<<sum<<endl;
      }
      

      6.尋根函數的實現

      //利用并查集性質,逐步回溯,找到一個頂點的“根”
       int Graph::findroot(int vertex){
          while(sets[vertex]!=vertex){
              vertex=sets[vertex];
          }
          return vertex;
      }
      

      7.對頂點按照權值排序函數的實現

      //按權值對頂點進行從小到大排序的函數
      void Graph::sortedges(){
          sort(edges.begin(),edges.end(),cmp);
      }
      

      8.測試部分。定義一個6個頂點9條邊的圖,調用接口求該圖的最小生成樹

      int main()
      {
          //實例化一個6個頂點,9條邊的圖對象
          Graph* G=new Graph(6,9);
          //調用接口實現算法
          G->kruscal();
          system("pause");
          return 0;
      }
      

      輸出

      控制臺輸出結果:
      控制臺輸出結果

      posted @ 2019-04-13 14:35  orion-orion  閱讀(535)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 久久丁香五月天综合网| 国产目拍亚洲精品二区| 无码人妻精品一区二区三区下载| 午夜福利高清在线观看| 久久这里有精品国产电影网| 婷婷四虎东京热无码群交双飞视频 | 综合成人亚洲网友偷自拍| 国产+亚洲+制服| 久久精产国品一二三产品| 国产成人综合色视频精品| 日韩人妻少妇一区二区三区| 国产高清在线a视频大全| 国产精品一品二区三区日韩| 中文字幕日韩精品人妻| 亚洲精品综合网二三区| XXXXXHD亚洲日本HD| 无码人妻丰满熟妇区五十路在线| 汉川市| 国产成人亚洲一区二区三区| 狂躁女人双腿流白色液体| 午夜爽爽爽男女免费观看影院| 啦啦啦中文在线观看日本| 久久精品夜夜夜夜夜久久| 久章草在线毛片视频播放| 国产精品亚洲二区在线看| 国产一区二区在线影院| 免费高潮了好湿h视频| 国产国拍精品av在线观看| 无码 人妻 在线 视频| 国产蜜臀视频一区二区三区| 孕妇特级毛片ww无码内射| 另类 专区 欧美 制服| 国产av综合一区二区三区| 欧美精品在线观看视频| 蜜芽久久人人超碰爱香蕉| 成年女人午夜毛片免费视频| 精品人妻av区乱码| 免费国产好深啊好涨好硬视频| 亚洲日韩图片专区第1页| 日本亚洲欧洲免费无线码| 特级做a爰片毛片免费看无码|