今天調程式淩晨3點了,終於調試通了,現在與大家分享:
例題:
無向圖的最小產生樹問題。
設G=[V,E]是一個無向圖,如果T=[V,E]是由G 的全部頂點及其一部分邊組成的子圖,T 是樹,則稱T 是G 的一個產生樹。記L(T)為T 的長度,即樹T 的各邊之和。求G 的所有
產生樹中L(T)最小的產生樹。
:
下面的兩棵樹都是圖G 的產生樹,其中T2 是所有圖G 的最小的產生樹。
最小產生樹的演算法思路是:由於n 個頂點的圖,其最小產生樹共有n-1 條邊,因此尋找最小
產生樹的問題就是選這n-1 條邊的過程,我們可以把這個過程分解為n-1 次的選擇,每次選
擇都選一條邊。在每次選邊的時候,我們採用貪心的原則:選擇一條權值最小而未被選過,
且和已選定的邊不會構成圈的邊。
最小產生樹的演算法如下:
T=空;
for i:=1 to n-1 do
begin
在圖G 中選取權值最小,不在T 中,而且與T 中的邊不構成圈的邊ei;
把ei 加入T 中;
end;
T 就是圖G 的最小產生樹。
#include <cstdlib>
#include <iostream>
#define LENGTH 100
#define Maxint 10000
using namespace std;
int main(int argc, char *argv[])
{
//圖G的點數N和邊數M
int N,M,i,j;
//對已選擇的邊ei,Selected[i]為1,否則為0
int Selected[LENGTH];
//邊的起點和終點
int E[LENGTH][2];
//邊的權值
int Value[LENGTH];
//若Vi是產生中的結點 ,T[i]=1,否則為0
int T[LENGTH];
//分別是當前選邊的權值‘選邊的編號和樹的長度
int Min,MinE,ValueT;
//讀入圖G,圖G採用邊目錄標記法
cin>>N>>M;
//初始化
for (i=0;i<M;i++)
cin>>E[i][0]>>E[i][1]>>Value[i];
for (i=0;i<LENGTH;i++)
{
Selected[i]=0;
T[i]=0;
}
ValueT=0;
//n-1次選邊過程
for (i=0;i<N-1;i++)
{
Min=Maxint;
MinE=0;
for(j=0;j<M;j++)
{
//未被選中
if (Selected[j]==0)
{
//不構成圈
if((T[E[j][0]]==0)^(T[E[j][1]]==0)||(i==0))
{
//權值最小
if (Value[j]<Min)
{
Min=Value[j];
MinE=j;
}}}
}
//做選中的標記
cout<<Min<<endl;
Selected[MinE]=1;
T[E[MinE][0]]=1;
T[E[MinE][1]]=1;
ValueT=ValueT+Min;
}
cout<<"T: :"<<"Length="<<ValueT<<endl;
for(i=0;i<M;i++)
if(Selected[i]==1)
{
cout<<"("<<E[i][0]<<","<<E[i][1]<<")"<<endl;
}
system("PAUSE");
return EXIT_SUCCESS;
}
測試資料如下:
6 7
1 2 3
1 6 2
2 3 5
2 5 2
3 4 1
4 5 4
5 6 1
程式運行結果如下:
T: Length=10
(1,6)
(2,5)
(3,4)
(4,5)
(5,6)