次小生成樹

2021-06-14 03:01:53 字數 2344 閱讀 7145

/*

*演算法引入:

*設g=(v,e,w)是連通的無向圖,t是圖g的一棵最小生成樹;

*如果有另一棵樹t1,滿足不存在樹t』,ω(t』)<ω(t1),則稱t1是圖g的次小生成樹;

* *演算法思想:

*鄰集的概念:由t進行一次可行交換得到的新的生成樹所組成的集合,稱為樹t的鄰集,記為n(t);

*設t是圖g的最小生成樹,如果t1滿足ω(t1)=min,則t1是g的次小生成樹;

*首先先求該圖的最小生成樹t,時間複雜度o(vlog2v+e);

*然後,求t的鄰集中權值和最小的生成樹,即圖g 的次小生成樹;

*如果只是簡單的列舉,複雜度很高;

*首先列舉兩條邊的複雜度是o(ve),再判斷該交換是否可行的複雜度是o(v),則總的時間複雜度是o(v2e);

*分析可知,每加入一條不在樹上的邊,總能形成乙個環,只有刪去環上的一條邊,才能保證交換後仍然是生成樹;

*而刪去邊的權值越大,新得到的生成樹的權值和越小,可以以此將複雜度降為o(ve);

*更好的方法:首先做一步預處理,求出樹上每兩個結點之間的路徑上的權值最大的邊;

*然後列舉圖中不在樹上的邊,有了預處理,就可以用o(1)的時間得到形成的環上的權值最大的邊;

*預處理:因為是一棵樹,只要簡單的bfs即可,預處理所要的時間複雜度為o(v2);

* *演算法測試:

*hdu4081(qin shi huang's national road system)(2011 asia beijing regional contest)

* *題目大意:

*有n個城市,秦始皇要修用n-1條路把它們連起來,要求從任一點出發,都可以到達其它的任意點,秦始皇希望這所有n-1條路長度之和最短;

*然後徐福突然有冒出來,說是他有魔法,可以不用人力、財力就變出其中任意一條路出來;

*秦始皇希望徐福能把要修的n-1條路中最長的那條變出來,但是徐福希望能把要求的人力數量最多的那條變出來;

*對於每條路所需要的人力,是指這條路連線的兩個城市的人數之和;

*秦始皇給出了乙個公式a/b,a是指要徐福用魔法變出的那條路所需人力,

*b是指除了徐福變出來的那條之外的所有n-2條路徑長度之和,選使得a/b值最大的那條;

* *演算法分析:

*為了使的a/b值最大,首先是需要是b盡量要小,所以可先求出n個城市的最小生成樹;

*然後就是決定要選擇哪一條邊用徐福的魔法來變;

*可以列舉每一條邊,假設最小生成樹的值是mst,而列舉的那條邊長度是g[i][j],

*如果這一條邊已經是屬於最小生成樹上的,那麼最終式子的值是a/(mst-g[i][j]);

*如果這一條不屬於最小生成樹上的,那麼新增上這條邊,就會有n條邊,那麼就會使得有了乙個環;

*為了使得它還是乙個生成樹,就要刪掉環上的一條邊,為了讓生成樹的權值盡量小,那麼就要刪掉除了加入的那條邊以外,權值最大的那條路徑;

*假設刪除的那個邊的權值是path[i][j],那麼就是a/(mst-path[i][j]);

*解這題的關鍵也在於怎樣求出次小生成樹,具體實現時,更簡單的方法是從每個節點i遍歷整個最小生成樹;

*定義path[i][j]為從i到j的路徑上最大邊的權值,遍歷圖求出path[i][j]的值;

*然後對於新增每條不在最小生成樹中的邊(i,j),新的生成樹權值之和就是mst+g[i][j]–path[i][j],其最小值則為次小生成樹;

**/#include#include#include#include#include#include#includeusing namespace std;

const int inf=99999999;

const int n=1010;

struct point

p[n];

double g[n][n],dist[n];

double path[n][n];//從i到j的路徑上最大邊的權值

int population[n];//每個城市的人口數

int pre[n],visit[n];

bool used[n][n];//邊是否在該mst中

int n;

inline double dist(point v1,point v2)

double prim()

for(int i=1; ig[u][j])//更新相鄰頂點的dist}}

}return mst;

}int main()

}double mst=prim();

double res=-1;

for(int i=1; i<=n; ++i)

}printf("%.2f\n",res);

}return 0;

}

最小生成樹 次小生成樹

一 最小生成樹 說到生成樹首先要解釋一下樹,樹是乙個聯通的無向無環圖,多棵樹的集合則被稱為森林。因此,樹具有許多性質 1.兩點之間的路徑是唯一的。2.邊數等於點數減一。3.連線任意兩點都會生成乙個環。對於乙個無向聯通圖g的子圖,如果它包含g的所有點,則它被稱為g的生成樹,而各邊權和最小的生成樹則被稱...

次小生成樹

分類 圖論 2013 02 12 15 03 32人閱讀收藏 舉報次小生成樹 在求最小生成樹時,用陣列path i j 來表示mst中i到j最大邊權。求完後,直接列舉所有不在mst中的邊,把它加入到mst中構成一棵新的樹,且該樹有環,此環是由剛加入的邊 i,j 造成的,所以可以通過刪除path i ...

次小生成樹

最小生成樹的演算法想必大家都很了解,主要有kruskal和prim。但如果要求次小生成樹 即第二小的生成樹 呢?一種容易想到的方法是列舉刪除最小生成樹上的邊,再求最小生成樹。用kruskal這種演算法的複雜度為o n elog2e 當圖比較稠密時,複雜度接近o n 3 但有一種更簡單的方法 先求最小...