hdu oj 1233 最小生成树 采用Prim算法

#include <stdio.h>
#include <string.h>

//随后的N(N-1)/2行对应村庄间的距离,每行给出一对正整数
//这里可以看出这是一个完全无向连通图
//很明显采用最小生成树解决


//这里采用邻接矩阵来存储

#define NMAX 100
#define NMIN 0xfffff

//主要是学习图数据结构,存储的时候还是定义规范点
typedef struct
{
    int no;
    int info;
}VertexType; //这个用来存储定点的信息的

typedef struct
{
    int edges[NMAX][NMAX];
    int n,e;
    //VertexType vxs[NMAX]; //存放定点的信息 //这里用不到
}MGrap;


//采用prim最小生成树算法
int Prim(MGrap g,int v)
{
    int res = 0;//记录所有边的和 

    int closest[NMAX]; //存储的是已经在最小生成树中的点

    int lowcost [NMAX]; //存储的是closest中点对应其他点的边的距离

    int m,i,flag,j;//flag用与标记找到的点
    for(i=1;i<=g.n;i++)
    {
        closest[i] = v; //其实这里存储的就是(v,i)这条边,只是这条边的长度保存在lowcost中
        lowcost[i] = g.edges[v][i]; //这里初始化(v,i)边距离
    }

    for(i=1;i<g.n;i++)//找出剩余的n-1个点
    {
        m=NMIN;
        for (j=1;j<=g.n;j++)
        {
            if(lowcost[j]!=0&&lowcost[j]<m)
            {
                m    = lowcost[j];
                flag = j;
            }
        }

        //将该条边的值加到res中
        res+=m;

        lowcost[flag] = 0; //将找到的定点加入到定点集中

        for(j=1;j<=g.n;j++)
        {
            //如果刚加入的点和其他点的边的长度所构成的候选边小于前面的候选边且不等于0
            //那么将改变改为候选边,删除原来那条候选边
            if(g.edges[flag][j]<lowcost[j]&&g.edges[flag][j]!=0)
            {
                closest[j] = flag; //修改边
                lowcost[j] = g.edges[flag][j];//修改候选边对应的长度
            }
        }
    }
    return res;
}

int main()
{
    int n,x,y,val,i;
    MGrap g;
    while (scanf("%d",&n)&&n)
    {
        memset(g.edges,NMIN,sizeof(g.edges));
        g.n = n;
        g.e = n*(n-1)/2;

        for (i=1;i<=n*(n-1)/2;i++)
        {
            scanf("%d %d %d",&x,&y,&val);
            g.edges[x][y] = val;
            g.edges[y][x] = val;
            if(i<=n)
            {
                g.edges[i][i]=0; //自己到自己为0
            }
        }

        printf("%d\n",Prim(g,1));
    }
    return 0;
}


对应的PHP实现Prim 代码(写的有点简单):

<?php
define("MAX",100);
define('MIN', 0xffffff);

//定义图
class MGrap
{
	public $n=0;
	public $e=0;
	public $edges = array(array());
}

function Prim(MGrap $g,$v)
{
	$closest = array();
	$lowcost = array();
	$res     = 0;
	for($i=1;$i<=$g->n;$i++)
	{
		$closest[$i] = $v; //初始化两个数组
		$lowcost[$i] = $g->edges[$v][$i];
		
	}
	$flag = -1; //标记当前找到的点
	for($i=1;$i<$g->n;$i++) //找出剩下的n-1个点
	{
		$min = MIN;
		for($j=1;$j<=$g->n;$j++)
		{
			if($lowcost[$j]<$min&&$lowcost[$j]!=0)
			{
				//找到对应的点
				$flag = $j;
				$min  = $lowcost[$j];
			}
		}
		$lowcost[$flag] = 0 ;//将找到的顶点加入到树的集合中
		$res+=$min;
		//修改数组
		for($j=1;$j<=$g->n;$j++)
		{
			if($g->edges[$flag][$j]<$lowcost[$j]&&$g->edges[$flag][$j]!=0)
			{
				$lowcost[$j] = $g->edges[$flag][$j];
				$closest[$j] = $flag;
			}
		}
		
	}
	return $res;
}

//这里只是为了测试直接初始化图

/* 
4
1 2 1
1 3 4
1 4 1
2 3 3
2 4 2
3 4 5

输出5
*/

$edg = array(
		1=>array(2=>1,3=>4,4=>1),
		2=>array(3=>3,4=>2),
		3=>array(4=>5)
		);
var_dump($edg);
$g = new MGrap();
$n = 4; //4个顶点
for($i=1;$i<=$n;$i++)
{
	for($j=1;$j<=$n;$j++)
	{
		if(isset($edg[$i][$j])&&$edg[$i][$j]!=0)
		{
			$g->edges[$i][$j] = $edg[$i][$j];
			$g->edges[$j][$i] = $edg[$i][$j];
		}
		
		if($i==$j)
		{
			$g->edges[$j][$i] = 0;
		}
	}
}

$g->n = $n;
$g->e = $n*($n-1)/2;
var_dump($g);
var_dump(Prim($g, 1));
?>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值