ACM--贪心算法

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值