之前學過最小生成樹,後來做題時遇到一些題目需要用次小生成樹的方法去求解,看了一些大牛的講解後,大概講一下自己的理解。
次小生成樹的定義就是所有生成樹中權值僅大於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 ...