prime算法用于解决wikioi 1003题
//1003 电话连线
//http://www.wikioi.com/problem/1003/
/********************************************************************
mst[]用父节点标注法,即mst[j]=i表示j的父亲节点是i
********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define MAX 110
#define MAXC 0x7fffffff
int n,m;
int map[MAX][MAX];//邻接矩阵
//mst[i]记录对应mincost[i]的起点,当mst[i]=0时表示起点i加入生成树
int mst[MAX];
//mincost[i]记录以i为终点的边的最小权值,当mincost[i]=0时表示终点i加入生成树
int mincost[MAX],edge[MAX][2]={0},flag[MAX]={0};
int prim(){
int i,j,min,minid,sum=0;
for(i=0;i<=n;i++)mincost[i]=-1;
//默认选择1号节点加入生成树,从2号节点开始初始化
for(i=2;i<=n;i++){
//短距离初始化为其他节点到1号节点的距离
mincost[i]=map[1][i];
//短距离初始化为其他节点到1号节点的距离
mst[i]=1;
}
//标记1号节点加入生成树
mst[1]=0;
for(i=2;i<=n;i++)
{
min = MAXC;
minid = 0;
//找满足条件的最小权值边的节点minid
for(j= 2;j<=n;j++)
{
// 边权值较小且不在生成树中
if(mincost[j]<min && mincost[j] != -1)
{
min = mincost[j];
minid = j;
}
}
//累加权值
sum+=min;
//标记节点minid加入生成树
mincost[minid] = -1;
if(min!=0){edge[m][0]=mst[minid];edge[m][1]=minid;m++;}
// 更新当前节点minid到其他节点的权值
for(j=2;j<=n;j++)
{
/* 发现更小的权值 */
if(map[minid][j]<mincost[j])
{
/* 更新权值信息 */
mincost[j]=map[minid][j];
/* 更新最小权值边的起点 */
mst[j] = minid;
}
}
}
/* 返回最小权值和 */
return sum;
}
int main(){
int i,j,ans;
scanf("%d",&n);
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)map[i][j]=MAXC;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&map[i][j]);
ans=prim();
printf("%d\n",m);
for(i=0;i<m;i++)
if(edge[i][0]>edge[i][1])printf("%d %d\n",edge[i][1],edge[i][0]);
else printf("%d %d\n",edge[i][0],edge[i][1]);
printf("%d\n",ans);
return 0;
}