最小生成樹入門(01 31)

2021-10-18 15:27:18 字數 3589 閱讀 2724

最小生成樹是一棵沒有迴路的樹,n個頂點一定有n-1條邊,同時也是乙個包含全部頂點的生成樹。最小生成樹就是給定一張邊帶權的無向聯通圖g=(v,e),n=|v|,m=|e|。由v中全部頂點和e中n-1條邊構成的無向聯通子圖被稱為g的一棵生成樹。邊的權值之和最小的生成樹被稱為無向圖g的最小生成樹(mst)。

最小生成樹中有用到貪心的思想,也就是在選擇邊的時候,每一步都要是最好的(即權重最小的邊)邊,並且只能用圖中的邊,也只能剛好用n-1條邊。

這裡介紹幾個最小生成樹的基本演算法

kruskal演算法就是在找最小生成樹結點之前,需要對邊權重從小到大進行排序。將排序好的權重邊一次加入帶最小生成樹中(如果形成迴路就continue),當加入的邊數為n-1條後,即為這個連通圖的最小生成樹。

這裡在排序的頂端也就是v1開始,選擇權重最小的邊也就是v1-v4這一條邊,同樣往下選擇了v6-v7、v3-v4、v1-v2這幾條邊。由於v2-v4、v1-v3這兩條邊加入會使之前的邊形成迴路,所以跳過不選,選擇v4-v7、v5-v7這兩條邊。這樣剛好6條邊(也就是n-1條邊),這樣我們的最小生成樹就構建好了。

當然為了查詢邊是否會成為迴路,這裡用到了並查集進行訪問。

#include

#include

#include

const

int maxn=

100;

int n,m,f[maxn]

;using

namespace std;

intget

(int x)

void

merge

(int x,

int y)

;struct edge

}aa[maxn*maxn]

;void

kurskal

(int n,

int m)

if(num==n-1)

break

;//邊有n-1條即為生成最小生成樹}if

(num==n-

1)cout<

//輸出最小權重

else cout<<

"?"<

}int

main()

return0;

}

prim演算法就是從任意乙個頂點開始生成最小生成樹,每次選擇乙個與當前小樹最近的乙個頂點,並將其加入到小樹中。然後更新這顆小樹到其他點的最近距離。

****最小生成樹prim演算法理解.

#include

#include

using

namespace std;

#define max 100

#define maxcost 0x7fffffff

int graph[max]

[max]

;int

prim

(int graph[

][max]

,int n)

mst[1]

=0;for

(i =

2; i <= n; i++)}

cout <<

"v"<< mst[minid]

<<

"-v"

<< minid <<

"="<< min << endl;

sum +

= min;

lowcost[minid]=0

;for

(j =

2; j <= n; j++)}

}return sum;

}int

main()

}//構建圖g

for(k =

1; k <= n; k++

)//求解最小生成樹

cost =

prim

(graph, m)

;//輸出最小權值和

cout <<

"最小權值和="

<< cost << endl;

system

("pause");

return0;

}

辨別最小生成樹的唯一性,首先要檢驗是否能生成最小生成樹,在生成的同時將每一條邊的序號儲存起來,在後面進行n-1次迴圈,每次迴圈去掉一條邊,若生成樹且權值等同於最小生成樹,則證明最小生成樹不唯一。

****最小生成樹的唯一性.

#include

#include

#include

#include

using

namespace std;

struct edge

;const

int maxn =

110;

int father[maxn]

;edge e[maxn * maxn]

;int map[maxn]

[maxn]

;int n, m;

int mst_edge[maxn]

;int

find

(int x)

father[x]

=find

(father[x]);

return father[x];}

intkruscal

(int count)

int k =0;

for(i =

1; i <= m && k < n -1;

++i)}/

*** 以下**是求解最小生成樹唯一性問題的核心**,其演算法思想如下:

* 在生成的最小生成樹的基礎上,一次刪除每一條邊,生成次小生成樹,

* 然後判斷次小生成樹的最小邊權值是否==最小生成樹的最小邊權值,

* 如果相等,則證明最小生成樹不唯一,否則證明所生成的最小生成樹唯一

**/int j;

for(i =

1; i <= n -1;

++i)

int ans2 =

0, k2 =0;

for(j =

1; j <= m;

++j)

int fx =

find

(e[j]

.begin)

;int fy =

find

(e[j]

.end);if

(fx != fy)}if

(k2 != n -1)

if(ans2 == sum)

}return sum;

}bool

compare

(const edge& a,

const edge& b)

//以上是用kruscal演算法來解決問題的基本模板.....

intmain()

sort

(e +

1, e + m +

1, compare)

;//kruscal演算法要求邊有序

int sum =

kruscal

(m);

if(sum ==-1

)else

}return0;

}

最小生成樹(入門題)

time limit 1000ms memory limit 65536k 有疑問?點這裡 有n個城市,其中有些城市之間可以修建公路,修建不同的公路費用是不同的。現在我們想知道,最少花多少錢修公路可以將所有的城市連在一起,使在任意一城市出發,可以到達其他任意的城市。輸入包含多組資料,格式如下。第一行...

最小生成樹 次小生成樹

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

最小生成樹

package 圖 最小生成樹是用最少的邊吧把所有的節點連線起來。於是和圖的深度優先搜素差不多。class stack public void push int key public int pop 檢視棧頂的元素 public int peek public boolean isempty cla...