程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 詳解次小生成樹和相干的C++求解辦法

詳解次小生成樹和相干的C++求解辦法

編輯:關於C++

詳解次小生成樹和相干的C++求解辦法。本站提示廣大學習愛好者:(詳解次小生成樹和相干的C++求解辦法)文章只能為提供參考,不一定能成為您想要的結果。以下是詳解次小生成樹和相干的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。依據引理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)。如許的算法顯得很自覺。經由簡略的
剖析不難發明,每參加一條不在樹上的邊,總能構成一個環,只要刪去環上的一條邊,能力
包管交流後依然是生成樹,而刪去邊的權值越年夜,新獲得的生成樹的權值和越小。我們可以
以此將龐雜度降為O(VE)。這曾經進步了一年夜步,但仍不敷好。
回想上一個模子——最小度限制生成樹,我們也曾面對過相似的成績,而且終究采取靜態規
劃的辦法防止了反復盤算,使得龐雜度年夜年夜下降。關於本題,我們可以采取相似的思惟。首
先做一步預處置,求出樹上每兩個結點之間的途徑上的權值最年夜的邊,然後,列舉圖中不在
樹上的邊,有了適才的預處置,我們便可以用O(1)的時光獲得構成的環上的權值最年夜的邊。
若何預處置呢?由於這是一棵樹,所以其實不須要甚麼精深的算法,只需簡略的BFS 便可。
預處置所要的時光龐雜度為O(V2)。
如許,這一步時光龐雜度降為O(V2)。
綜上所述,次小生成樹的時光龐雜度為O(V2)。

演習
標題:

    標題描寫: 
    最小生成樹年夜家都曾經很懂得,次小生成樹就是圖中組成的樹的權值和第二小的樹,此值也能夠等於最小生成樹的權值和,你的義務就是設計一個算法盤算圖的最小生成樹。 
    輸出: 
    存在多組數據,第一行一個正整數t,表現有t組數據。 
    每組數據第一行有兩個整數n和m(2<=n<=100),以後m行,每行三個正整數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; // 記載最小生成樹用到邊的數目 
   
  typedef struct node { 
    int st, ed, w; 
  } node; 
   
  /** 
   * 預處置並查集數組 
   */ 
  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; 
  } 
   
  /** 
   * 並查集尋覓肇端結點,途徑緊縮優化 
   */ 
  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; 
  } 



  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved