最小生成樹構造
實驗目的
熟悉最小生成樹的構造算法,掌握最小生成樹的構造過程。
實驗內容與要求
定義1 設T是一個連通且迴路的無向圖,則稱T爲無向樹,簡稱樹。樹中度數爲1的結點稱爲樹葉,度數大於1的結點稱爲分枝點(或內點)。
定義2設G=<V,E>是一個連通的無向圖,若G的某個生成子圖是一棵樹,則稱該樹爲G的生成樹,記爲TG。
定義3假定圖G是具有n個結點的連通圖。對應於G的每一條邊e,指定一個正數C(e),把C(e)稱作邊e的權,(可以是長度、運輸量、費用等)。G的生成樹也具有一個樹權C(T),它是T的所有邊權的和。
定義4 在帶權的圖G的所有生成樹中,樹權最小的那棵生成樹,稱作最小生成樹。
定理1 (Kruskal)
設圖G有n個結點,執行如下步驟
⑴ 選擇權最小的邊e1,置邊數i←1;
⑵ i=n-1結束,否則轉⑶;
⑶ 設定已選定e1,e2,,…,ei,在G中選取不同於e1,e2,,…,ei的邊ei+1,使{e1,e2,,…,ei,ei+1}無迴路且ei+1是滿足此條件的權最小的邊。
⑷ i←i+1,轉⑵。
本實驗要求從鍵盤輸入一個賦權圖(邊權,以矩陣形式輸入),求出對應的最小生成樹。用C語言或MATLAB實現。
源程序
#include<iostream>
using namespace std;
int n,**a;
bool **b,**c,d=0;
bool bestTree(int);
void Closure();
int main()
{
int i;
cout<<"請輸入帶權圖結點個數:";
cin>>n;
a=new int*[n];
b=new bool*[n];
c=new bool*[n];
for(i=0;i<n;i++)
{
a[i]=new int[n];
b[i]=new bool[n];
c[i]=new bool[n];
}
cout<<"請輸入帶權圖:"<<endl;
for(i=0;i<n;i++)
for(int j=0;j<n;j++)
{
b[i][j]=0;
c[i][j]=0;
cin>>a[i][j];
}
bestTree(n-1);
for(i=0;i<n;i++)
for(int j=i;j<n;j++)
if(b[i][j]==1)
b[j][i]==1;
cout<<"最優樹爲:"<<endl;
for(i=0;i<n;i++)
{
for(int j=0;j<n;j++)
cout<<b[i][j]<<' ';
cout<<endl;
}
return 0;
}
bool bestTree(int m)
{
if(m==0)
d=1;
if(d==1)
return 0;
int i,min=-1,fi,fj;
for(i=0;i<n;i++)
for(int j=i;j<n;j++)
if(((a[i][j]>0)&&a[i][j]<min)||(a[i][j]>0)&&min==-1)
{
min=a[i][j];
fi=i;fj=j;
}
a[fi][fj]=-1;
if(c[fi][fj]==1||c[fj][fi]==1)
{
bestTree(m);
return 0;
}
b[fi][fj]=1;
Closure();
bestTree(m-1);
}
void Closure()
{
int i,t[10],x=0;
for(i=0;i<n;i++)
for(int j=i;j<n;j++)
c[i][j]=b[i][j];
for(i=0;i<n;i++)
for(int j=0;j<n;j++)
if(c[j][i]==1)
for(int k=0;k<n;k++)
c[j][k]+=c[i][k];
for(i=0;i<n;i++)
{
int j;
for(j=i;j<n;j++)
if(c[i][j]==1)
t[x++]=j;
for(j=0;j<x-1;j++)
c[t[j]][t[j+1]]=1;
}
}
示例結果