次小生成樹

2021-06-21 12:46:57 字數 1409 閱讀 4158

最小生成樹的演算法想必大家都很了解,主要有kruskal和prim。但如果要求次小生成樹(即第二小的生成樹)呢?

一種容易想到的方法是列舉刪除最小生成樹上的邊,再求最小生成樹。用kruskal這種演算法的複雜度為o(n*elog2e),當圖比較稠密時,複雜度接近o(n^3)。

但有一種更簡單的方法:先求最小生成樹t,列舉新增不在t中的邊,則新增後一定會形成環。找到環上邊值第二大的邊(即環中屬於t中的最大邊),把它刪掉,計算當前生成樹的權值,取所有列舉修改的生成樹的最小值,即為次小生成樹。

這種方法在實現時有更簡單的方法:首先求最小生成樹t,然後從每個結點u遍歷最小生成樹t,用乙個二維陣列max[u][v]記錄結點u到結點v的路勁上邊的最大值(即最大邊的值)。然後列舉不在t中的邊(u,v),計算t- max[u][v] + w(u,v)的最小值,即為次小生成樹的權值。顯然,這種方法的時間複雜度為o(n^2 + e)。

可見,第二種演算法將原來的時間複雜度o(n^3)提高到了o(n^2)。

例:判斷生成樹的唯一性,唯一則輸出權值,不唯一輸出not unique!(poj1679)

顯然,可以轉化為求次小生成樹,次小生成樹權值=最小生成樹,則不唯一。

#include #include #include const int inf = 0x7fffffff;

const int max = 10001;

int n,m;

int num;

int p[max];

int max[101][101];

struct edge //原始圖

e[max];

struct tree //最小生成樹

tree[202];

int index[101];

struct node //生成樹的結點

;bool cmp(const edge &a, const edge &b)

void makeset()

}int findset(int x)

void addedge(int from, int to, int w)

int kruscal()

} return edgenum == n-1 ? result : -1;

}void bfs(int p)

} }}void second_mst()

} if(smst == mst)

printf("not unique!\n");

else

printf("%d\n",mst);

}int main()

num = 0;

memset(index,-1,sizeof(index));

second_mst();

} return 0;

}

最小生成樹 次小生成樹

一 最小生成樹 說到生成樹首先要解釋一下樹,樹是乙個聯通的無向無環圖,多棵樹的集合則被稱為森林。因此,樹具有許多性質 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 ...