今天调程序凌晨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)