#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));
?>