欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解次小生成樹以及相關的C++求解方法

 更新時間:2015年08月07日 11:19:30   作者:zinss26914  
這篇文章主要介紹了詳解次小生成樹以及相關的C++求解方法,文中的練習示例采用了kruskal算法通過C++進行求解,需要的朋友可以參考下

次小生成樹的定義
設 G=(V,E,w)是連通的無向圖,T 是圖G 的一個最小生成樹。如果有另一棵樹T1,滿
足不存在樹T',ω(T')<ω(T1) ,則稱T1是圖G的次小生成樹。

求解次小生成樹的算法
約定:由T 進行一次可行交換得到的新的生成樹所組成的集合,稱為樹T的鄰集,記為N(T)。
定理 3:設T是圖G的最小生成樹,如果T1滿足ω(T1)=min{ω(T')| T'∈N(T)},則T1是G
的次小生成樹。
證明:如果 T1 不是G 的次小生成樹,那么必定存在另一個生成樹T',T'=T 使得
ω(T)≤ω(T')<ω(T1),由T1的定義式知T不屬于N(T),則
E(T')/E(T)={a1,a2
1,……,at},E(T)/E(T')={b1,b2,……,bt},其中t≥2。根據(jù)引理1 知,存在一
個排列bi1,bi2,……,bit,使得T+aj-bij仍然是G 的生成樹,且均屬于N(T),所以ω(aj)≥ω(bij),
所以ω(T')≥ω(T+aj-bij)≥ω(T1),故矛盾。所以T1是圖G 的次小生成樹。
通過上述定理,我們就有了解決次小生成樹問題的基本思路。
首先先求該圖的最小生成樹T。時間復雜度O(Vlog2V+E)
然后,求T的鄰集中權值和最小的生成樹,即圖G 的次小生成樹。
如果只是簡單的枚舉,復雜度很高。首先枚舉兩條邊的復雜度是O(VE),再判斷該交換是否
可行的復雜度是O(V),則總的時間復雜度是O(V2E)。這樣的算法顯得很盲目。經過簡單的
分析不難發(fā)現(xiàn),每加入一條不在樹上的邊,總能形成一個環(huán),只有刪去環(huán)上的一條邊,才能
保證交換后仍然是生成樹,而刪去邊的權值越大,新得到的生成樹的權值和越小。我們可以
以此將復雜度降為O(VE)。這已經前進了一大步,但仍不夠好。
回顧上一個模型——最小度限制生成樹,我們也曾面臨過類似的問題,并且最終采用動態(tài)規(guī)
劃的方法避免了重復計算,使得復雜度大大降低。對于本題,我們可以采用類似的思想。首
先做一步預處理,求出樹上每兩個結點之間的路徑上的權值最大的邊,然后,枚舉圖中不在
樹上的邊,有了剛才的預處理,我們就可以用O(1)的時間得到形成的環(huán)上的權值最大的邊。
如何預處理呢?因為這是一棵樹,所以并不需要什么高深的算法,只要簡單的BFS 即可。
預處理所要的時間復雜度為O(V2)。
這樣,這一步時間復雜度降為O(V2)。
綜上所述,次小生成樹的時間復雜度為O(V2)。

練習
題目:

    題目描述: 
    最小生成樹大家都已經很了解,次小生成樹就是圖中構成的樹的權值和第二小的樹,此值也可能等于最小生成樹的權值和,你的任務就是設計一個算法計算圖的最小生成樹。 
    輸入: 
    存在多組數(shù)據(jù),第一行一個正整數(shù)t,表示有t組數(shù)據(jù)。 
    每組數(shù)據(jù)第一行有兩個整數(shù)n和m(2<=n<=100),之后m行,每行三個正整數(shù)s,e,w,表示s到e的雙向路的權值為w。 
    輸出: 
    輸出次小生成樹的值,如果不存在輸出-1。 
    樣例輸入: 
    2 
    3 3 
    1 2 1 
    2 3 2 
    3 1 3 
    4 4 
    1 2 2 
    2 3 2 
    3 4 2 
    4 1 2 
    樣例輸出: 
    4 
    6 


ac代碼(注釋寫的比較清楚):

   

 #include <stdio.h> 
  #include <stdlib.h> 
  #include <string.h> 
   
  #define MAX 100000 
   
  int father[210];  // 并查集 
  int visit[210]; // 記錄最小生成樹用到的邊的下標 
  int windex; // 記錄最小生成樹用到邊的數(shù)量 
   
  typedef struct node { 
    int st, ed, w; 
  } node; 
   
  /** 
   * 預處理并查集數(shù)組 
   */ 
  void preProcess() 
  { 
    int i, len = sizeof(father) / sizeof(father[0]); 
   
    for (i = 0; i < len; i ++) { 
      father[i] = i; 
    } 
   
  } 
   
  /** 
   * kruskal使用貪心算法,將邊按權值從小到大排序 
   */ 
  int cmp(const void *p, const void *q) 
  { 
    const node *a = p; 
    const node *b = q; 
   
    return a->w - b->w; 
  } 
   
  /** 
   * 并查集尋找起始結點,路徑壓縮優(yōu)化 
   */ 
  int findParent(int x) 
  { 
    int parent; 
   
    if (x == father[x]) { 
      return x; 
    } 
   
    parent = findParent(father[x]); 
    father[x] = parent; 
     
    return parent; 
  } 
   
  /** 
   * 求最小生成樹 
   */ 
  int minTree(node *points, int m, int n) 
  { 
    preProcess(); 
   
    int i, count, flag, pa, pb; 
   
    for (i = count = flag = windex = 0; i < m; i ++) { 
      pa = findParent(points[i].st); 
      pb = findParent(points[i].ed); 
       
      if (pa != pb) { 
        visit[windex ++] = i; 
        father[pa] = pb; 
        count ++; 
      } 
   
      if (count == n - 1) { 
        flag = 1; 
        break; 
      } 
    } 
   
    return flag; 
  } 
   
  /** 
   * 求次小生成樹 
   */ 
  int secMinTree(node *points, int m, int n) 
  { 
    int i, j, min, tmp, pa, pb, count, flag; 
   
    for (i = 0, min = MAX; i < windex; i ++) { 
      preProcess(); 
   
      // 求次小生成樹 
      for (j = count = tmp = flag = 0; j < m; j ++) { 
        if (j != visit[i]) { 
          pa = findParent(points[j].st); 
          pb = findParent(points[j].ed); 
   
          if (pa != pb) { 
            count ++; 
            tmp += points[j].w; 
            father[pa] = pb; 
          } 
   
          if (count == n - 1) { 
            flag = 1; 
            break; 
          } 
        } 
      } 
   
      if (flag && tmp < min)  min = tmp; 
    } 
   
    min = (min == MAX) ? -1 : min; 
   
    return min;  
  } 
   
   
  int main(void) 
  { 
    int i, t, n, m, flag, min; 
    node *points; 
   
    scanf("%d", &t); 
   
    while (t --) { 
      scanf("%d %d", &n, &m); 
   
      points = (node *)malloc(sizeof(node) * m);  
   
      for (i = 0; i < m; i ++) { 
        scanf("%d %d %d", &points[i].st, &points[i].ed, &points[i].w); 
      } 
   
      qsort(points, m, sizeof(points[0]), cmp); 
       
      flag = minTree(points, m, n); 
   
      if (flag == 0) {  // 無法生成最小生成樹 
        printf("-1\n"); 
        continue; 
      } else { 
        min = secMinTree(points, m, n); 
        printf("%d\n", min); 
      } 
   
   
      free(points); 
    } 
   
    return 0; 
  } 



相關文章

  • C++編程中break語句和continue語句的學習教程

    C++編程中break語句和continue語句的學習教程

    這篇文章主要介紹了C++編程中break語句和continue語句的學習教程,break和continue是C++循環(huán)控制中的基礎語句,需要的朋友可以參考下
    2016-01-01
  • C++ 基類指針和子類指針相互賦值的實現(xiàn)方法

    C++ 基類指針和子類指針相互賦值的實現(xiàn)方法

    下面小編就為大家?guī)硪黄狢++ 基類指針和子類指針相互賦值的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-12-12
  • C語言static修飾函數(shù)詳細解析

    C語言static修飾函數(shù)詳細解析

    以下是對C語言中的static修飾函數(shù)進行了詳細的分析介紹,需要的朋友可以過來參考下
    2013-08-08
  • c++?qt自定義搜索編輯框的實現(xiàn)方法

    c++?qt自定義搜索編輯框的實現(xiàn)方法

    這篇文章主要介紹了c++?qt自定義搜索編輯框,通過自定義QLineEdit,在編輯框里添加布局,將按鈕設置在右邊,當點擊按鈕搜索按鈕時發(fā)送信號到主界面做相應的操作,需要的朋友可以參考下
    2022-03-03
  • Matlab實現(xiàn)帶豎線散點的核密度圖的繪制

    Matlab實現(xiàn)帶豎線散點的核密度圖的繪制

    核密度估計是用于估計隨機變量概率密度函數(shù)的一種非參數(shù)方法。核密度圖不失為一種用來觀察連續(xù)型變量分布的有效方法。本文將用Matlab實現(xiàn)帶豎線散點的核密度圖的繪制,感興趣的可以了解一下
    2022-08-08
  • C語言實現(xiàn)反彈球游戲

    C語言實現(xiàn)反彈球游戲

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)反彈球游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • C/C++語言宏定義使用實例詳解

    C/C++語言宏定義使用實例詳解

    這篇文章主要介紹了 C/C++語言宏定義使用實例詳解的相關資料,需要的朋友可以參考下
    2017-06-06
  • 算法之排列算法與組合算法詳解

    算法之排列算法與組合算法詳解

    這篇文章主要介紹了算法之排列算法與組合算法詳解,本文以字典序法、遞歸法為例講解了排列算法、全組合算法等,需要的朋友可以參考下
    2014-08-08
  • C語言實現(xiàn)輸入兩個數(shù)字將其按從小到大輸出的方法

    C語言實現(xiàn)輸入兩個數(shù)字將其按從小到大輸出的方法

    這篇文章主要介紹了C語言實現(xiàn)輸入兩個數(shù)字將其按從小到大輸出的方法,本文通過代碼講解的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • 從匯編看c++中引用與指針的使用分析

    從匯編看c++中引用與指針的使用分析

    在c++中,引用和指針具有相同的作用,都可以用來在函數(shù)里面給變函數(shù)外面對象或者變量的值,下面就來看他們的原理
    2013-05-05

最新評論