次小生成樹題目及思路 poj1679

2021-08-18 20:30:44 字數 1385 閱讀 2444

下面只是講講我對次小生成樹一些理解,推薦先去看一下次小生成樹的一些概念再來看這篇部落格。

首先我們要明確一點,在最小生成樹中,任意兩個點之間有且僅有一條路徑。然後是次小生成樹由何而來,必然是最小生成樹轉變而來。如何轉變,應該是將一條不是最小生成樹中的邊,替換最小生成樹的一條邊,且替換後任意節點之間還應該有通路。那麼思路就來了。由於最小生成樹的特點,因此往樹中新增一條邊,就必然會形成乙個環,那麼去掉的邊也應該是環上屬於最小生成樹的某一條邊。大體思路就是這個樣子。

1.先形成最小生成樹,同時對於需要標記屬於最小生成樹的邊,下面**用vis來標記。

2.在每次選取乙個離生成樹最近的乙個點後,需要列舉所有已經加入最小生成樹的點,依次更新max陣列,max[i][j]表示在i節點和j節點的路徑上最小生成樹的最大權值(因為在最後列舉不是最小生成樹的邊的時候,顯然去掉環上權值最大的邊才能使次小生成樹的總值盡可能的小)。而max[i][j]的更新是dp的思想,建議好好理解。

3.最後就是列舉所有不在最小生成樹上的邊,依次更新次小生成樹。

下面的**是poj1679的題。

就是詢問所給出的資料所形成的最小生成樹是否為一。

如何判斷唯一,只需要判斷次小生成樹是否和最小生成樹相等就行了。

#include 

#include

#include

#include

#include

#include

#define inf 0x3f3f3f3f

using

namespace

std;

typedef pairpii;

const

int maxn = 105;

int e[maxn][maxn];//圖

int vis[maxn][maxn];//標記邊

int dis[maxn];//原本是距離陣列,但是因為是求最小生成樹,因此也可以

int pre[maxn];//前驅節點

int max[maxn][maxn];//記錄最大權值的邊

int t, n, m;

int sum;//最小生成樹

int minsum;//次小生成樹

//bool cmp(pii a,pii b)

void prim()

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

if(dis[i] > e[i][v]) }}

}void solve() }}

if(minsum == sum) else

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

}int main()

prim();

solve();

}return

0;}

題目1249 次小生成樹

題目1249 次小生成樹 時間限制 1 秒 記憶體限制 32 兆 特殊判題 否 提交 140 解決 37 題目描述 最小生成樹大家都已經很了解,次小生成樹就是圖中構成的樹的權值和第二小的樹,此值也可能等於最小生成樹的權值和,你的任務就是設計乙個演算法計算圖的最小生成樹。輸入 存在多組資料,第一行乙個...

POJ 1679 次小生成樹

判斷最小生成樹是否唯一,方法是這樣的 1.對圖中每個點,掃瞄其他的邊,如果存在其他權值相同的邊,則對改邊作標記 2.然後用 kruskal或者prim 求mst 3.求的mst後,如果該mst不包含作了標記的邊,即可判定mst唯一 如果包含作了標記的邊,則依次去掉這些邊在求mst,如果求的mst權值...

POJ3255(次小生成樹)

次小生成樹裸題 到某個點的次小次短路要麼是其它某個點u的最短路加上u v的邊,要麼就是到u的次短路加上u v的邊,因此所需要求的就是到所有頂點的最短路和次短路 include include include include include using namespace std const int ...