未参考题解写的
/*
http://acm.hdu.edu.cn/showproblem.php?pid=1102
*/
#include <stdio.h>
#include <string.h>
#define INF 100000000
int tree[110][110];
int intree[110];
int nontree[110];
int main()
{
freopen("input.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF)
{
memset(tree,0,sizeof(tree));
memset(intree,0,sizeof(intree));
memset(nontree,0,sizeof(nontree));
int i,j;
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
scanf("%d",&tree[i][j]);
int m,a,b;
scanf("%d",&m);
for(i=1; i<=m; i++)
{
scanf("%d %d",&a,&b);
tree[a][b]=tree[b][a]=0;//让已经相连的村庄之间的长度为0
}
intree[1]=1;//选取第一个村庄为起始点
int non=0; // 未加入MST的村庄
for(i=1; i<=n; i++)
{
if(!intree[i])
{
non++; nontree[i]=1;
}
}
int sum=0;
while(non)
{
int min = INF,vi=0,vj=0;
for(i=1; i<=n; i++) //已加入MST的村庄
{
if(!intree[i]) continue;
for(j=1; j<=n; j++) // 为加入MST的村庄
{
if(!nontree[j]) continue;
if(min>tree[i][j])
{
min = tree[i][j];
vj=j; vi=i;
}
}
}
if(vj)//找到最小路径
{
intree[vj]=1; nontree[vj]=0;
non--;
sum += tree[vi][vj];
}
}
printf("%d\n",sum);
}
return 0;
}
参考了网上的题解写的代码
prim 算法
/*
http://acm.hdu.edu.cn/showproblem.php?pid=1102
*/
#include <stdio.h>
#include <string.h>
#include <limits.h>
int tree[110][110]; //邻接矩阵表示点与点之间的距离
int visit[110]; //是否已加入 MST
int lowcost[110]; // 每个未加入 MST的点与已加入MST的点之间的 最短距离
int sum,n; // 总的最小费用 和 点的个数
void prim()
{
visit[1]=1;//选择第一个点作为起始点
int i,j;
for(i=2; i<=n; i++)
lowcost[i]=tree[1][i]; //与第一个点相连的费用
for(i=2; i<=n; i++) //将剩余的n-1个点 加入到 MST
{
int min=0xfffffff,k=0;
for(j=2; j<=n; j++) //选择 加入MST 的点 和未加入 MST的点之间的 最短距离
{
if(!visit[j] && min>lowcost[j])
{
min = lowcost[j];
k=j;
}
}
sum += min;
visit[k]=1;
/*
更新 lowcost 数组
如果刚加入 MST 的节点 k 与 为加入MST的 节点 j 之间的 距离
比 节点 j 与 之前加入MST的节点 的距离 小 则 将lowcost[j]的值设为k与j的距离即tree[k][j]
*/
for(j=2; j<=n; j++)
{
if(!visit[j] && tree[k][j]<lowcost[j])
lowcost[j]=tree[k][j];
}
}
}
int main()
{
freopen("input.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
memset(tree,0,sizeof(tree));
memset(visit,0,sizeof(visit));
memset(lowcost,0,sizeof(lowcost));
int i,j;
sum=0;
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
scanf("%d",&tree[i][j]);
int m,a,b;
scanf("%d",&m);
for(i=1; i<=m; i++)
{
scanf("%d %d",&a,&b);
/*
将已经修好的路 长度设为0 在 以后的构造最小生成树时
这些修好的路 一定会被 加入到最小生成树中 而且 对于最后统计的 最小费用没有影响
*/
tree[a][b]=tree[b][a]=0;
}
prim();
printf("%d\n",sum);
}
return 0;
}
kruskal 算法
/*
http://acm.hdu.edu.cn/showproblem.php?pid=1102
kruskal 算法
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct edge{ //表示边
int a,b; //边的两个顶点
int weight;//边的权值
} edge;
edge road[110*110/2];//边的集合 n 个顶点最多 n*(n+1)/2 条边
int p[110]; //表示顶点的父节点
int tree[110][110]; //邻接矩阵
int find(int x)
{
return p[x]==x?x:find(p[x]);
}
void merge(int x, int y)
{
int px,py;
px = find(x);
py = find(y);
if(px!=py)
p[py]=px;
}
int cmp(const void* a, const void*b)
{
return ((edge*)a)->weight- ((edge*)b)->weight;
}
int main()
{
freopen("input.txt","r",stdin);
int n;
while(scanf("%d",&n)!=EOF)
{
memset(road,0,sizeof(road));
memset(tree,0,sizeof(tree));
int i,j,e=0;
for(i=1; i<=110; i++) p[i]=i; //初始化 p 数组
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
scanf("%d",&tree[i][j]);
for(i=1; i<=n; i++) //初始化边的集合
{
for(j=i+1; j<=n; j++)
{
road[e].a=i;
road[e].b=j;
road[e].weight=tree[i][j];
e++;
}
}
int m,a,b;
scanf("%d",&m);
for(i=1; i<=m; i++)
{
scanf("%d %d",&a,&b);
merge(a,b);
}
qsort(road,e,sizeof(road[0]),cmp); //将边根据权值 从小到大排序
int sum=0;
for(i=0; i<e; i++) //根据权值 从小到大 将边加入 MST
{
int pa,pb;
pa=road[i].a;
pb=road[i].b;
if(find(pa)!=find(pb)) //如果边的两个顶点还没通路,则将该边加入
{
sum += road[i].weight;
merge(pa,pb);
}
}
printf("%d\n",sum);
}
return 0;
}