次小生成樹

2021-07-26 10:26:28 字數 1714 閱讀 1790

之前學過最小生成樹,後來做題時遇到一些題目需要用次小生成樹的方法去求解,看了一些大牛的講解後,大概講一下自己的理解。

次小生成樹的定義就是所有生成樹中權值僅大於mst的(假設mst只有一棵如果有兩棵那我們隨便欽定一棵樹就可以了)。

現在有一些可以利用的結論:

1、在給定的圖中,次小生成樹至少有一條邊不是mst的邊。

證明:比較顯然,具體我也不會……

2、次小生成樹是給定的圖中某條不在mst中的邊對應的最小生成樹。

證明:也比較顯然,具體我也不會……

3、所求的次小生成樹除了2中所說的那條不在mst中的邊,其他的邊其實都在mst中。

證明:這裡不太明顯,但是我還是不會……不過利用一下反證法好像可以說得通。假設有次小生成樹t1  v1 v2 v3 v4四個點屬於t1,v1,v2是用不在mst中的邊連線起來的點,且v3,v4也不是用mst中的邊連線起來,那麼v3和v4若用mst的邊連線起來形成的生成樹則比t1的權值更小且該樹不是mst。

經過上面證明我們大概就知道其實次小生成樹就是mst刪掉一條邊,然後形成兩個連通塊,再用圖中某條邊把這兩個連通塊連線起來,就是次小生成樹了。

演算法過程大概是

1、列舉圖中不在mst的邊

2、然後只加入這條邊的基礎上,我們對這個圖跑一次kruskal或者是prim,

3、實際上2中我們prim或者kruskal需要用到的邊只有mst中的邊。

複雜度是o(v * e)

有大佬的方法是

1、列舉不在mst的邊,假設連線u,v

2、在mst中加入這條邊,(實際上相當於u,v成了乙個環)

3、刪除掉mst中u,v這條路徑上最長的邊。

3中的方法可以用樹鏈剖分來實現,貌似lca也可以,複雜度是log v

總的複雜度是o(e *logv ) 

可惜的是,我不會……

貼一下方法1的**,方法2尚在學習中

#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;

#define long long long

const long inf=0x3f3f3f3f;

const long mod=1e9+7;

const double pi=acos(-1.0);

#define clri(x) memset(x,-1,sizeof(x))

#define clr0(x) memset(x,0,sizeof x)

#define clr1(x) memset(x,inf,sizeof x)

#define clr2(x) memset(x,-inf,sizeof x)

#define eps 1e-10

struct edge

edge[20000];

int fa[2000];

int found(int x)

bool cmp(edge a, edge b)

int tot = 0;

struct mst_edgemst_edge[20000];

bool use[20000];

int head[2000];

void add(int u , int v, int w)

void init()

int main()

}// cout<

最小生成樹 次小生成樹

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

次小生成樹

演算法引入 設g v,e,w 是連通的無向圖,t是圖g的一棵最小生成樹 如果有另一棵樹t1,滿足不存在樹t t t1 則稱t1是圖g的次小生成樹 演算法思想 鄰集的概念 由t進行一次可行交換得到的新的生成樹所組成的集合,稱為樹t的鄰集,記為n t 設t是圖g的最小生成樹,如果t1滿足 t1 min,...

次小生成樹

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