前言:
最小生成树问题,这里利用Prim算法来解:
关键点:
1、首先是初始化,dist数组,既为判断是否被加入树中,也代表了该结点与上个结点的最小距离,初始化为最大值,同样,代表两条路连通花费的cost数组也初始化为最大值,处理自己到自己的cost初始化为0
for (int i=1; i<=n; i++)
{
dist[i] = INF;
for (int j=1; j<=n; j++)
{
if (i==j)
cost[i][j] = 0;
else
cost[i][j] = INF;
}
}
2、利用与Dijkstra算法类似的思想,先从第一个结点开始作为起始点,注意要有一个计数器来记当前收入树中的结点,方便后序判断是否可以生成最小生成树。
完整代码:
# include <stdio.h>
# define INF 100000
long long n, m, totalweight;
int cost[1000+10][1000+10];
int dist[1000+10];
int prim()
{
int vcount = 0;
for (int i=1; i<=n; i++)
{
if (cost[i][i]<INF)
dist[i] = cost[1][i];
}
dist[1] = 0;
vcount++;
while (1)
{
int Min = INF;
int k;
//找到未被收进树里的最小的dist值
for (int i=1; i<=n; i++)
{
if (dist[i]!=0&&dist[i]<Min)
{
k = i;
Min = dist[i];
}
}
if (Min==INF)
break;
//加上此时选中的cost值
totalweight+=dist[k];
//设为0,表示该点已收取
dist[k] = 0;
//收入树结点个数加一,方便后序判断是否所有结点都收入
vcount++;
for (int i=1; i<=n; i++)
{
if (dist[i]!=0&&cost[i][k]<INF)
{
if (dist[i]>cost[i][k])
{
dist[i] = cost[i][k];
}
}
}
}
if (vcount<n)
return -1;
else
return totalweight;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i=1; i<=n; i++)
{
dist[i] = INF;
for (int j=1; j<=n; j++)
{
if (i==j)
cost[i][j] = 0;
else
cost[i][j] = INF;
}
}
for (int i=1; i<=m; i++)
{
int x, y, cos;
scanf("%d%d%d", &x, &y, &cos);
cost[x][y] = cos;
cost[y][x] = cos;
}
printf("%d", prim());
return 0;
}