最小生成樹是一棵沒有迴路的樹,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...