#define _CRT_SECURE_NO_WARNINGS 1
//prim算法,最小生成树
/*
* 每次选择离树最近的一个并且未被访问的点,然后
* 更新与此点相邻的且未被访问的点的值
*/
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef struct node
{
int x;
int y;
}NODE;
NODE node[105];
double a[105][105]; //记录边的值 ,第i个点与第j个点间的距离
bool visit[105]; //是否访问过
double dist[1005]; //此节点最小的连接距离
int n;
double prim();
int main(void)
{
//初始化
for (int i = 0; i < 105; i++)
{
visit[i] = false;
dist[i] = 9999999;
}
//输入节点个数与坐标
cin >> n;
for (int i = 1; i <= n; i++)
cin >> node[i].x >> node[i].y;
//(初始化)更新边的值
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
a[i][j] = a[j][i] = sqrt(pow(node[i].x - node[j].x, 2) + pow(node[i].y - node[j].y, 2));
//测试图是否建立正确
/*for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
cout << a[i][j] << ' ';
cout << "\n";
}*/
printf("%.2lf", prim());
return 0;
}
//dist[1]置为0,代表从此开始,或者是说目前树只有此一个节点,故一定从此开始
//while循环n次,代表每次都能选出一个点
//第一个for循环是为了找到离树最近的一个并且未被访问的点
//sum加上这个最小值,然后这个点标记为访问过
/* 循环更新与此点相连的点的dist距离,这里更新dist的同时说明第i个节点与树相连
然后上面一个循环中,未更新的点是一个最大值,更新过的点修改了,所以也间接表示了
与树相连的点*/
double prim()
{
double sum = 0;
int t = n;
int temp = 1;
dist[temp] = 0;
//找n次,n个点全部都修改到
while (t--)
{
temp = 0;
//循环找到离上一个点最近的点
for (int i = 1; i <= n; i++)
{
if (!visit[i] && (temp == 0 || dist[i] < dist[temp]))
temp = i;
}
//结果加上这个找到的最小的权值
sum += dist[temp];
//状态修改为修改过,下次不再修改
visit[temp] = true;
//更新权值
for (int i = 1; i <= n; i++)
if (!visit[i])
dist[i] = min(dist[i], a[temp][i]);
}
return sum;
}
注意边的值的刷新,可能存在重复边;注意提前退出若无法全部连通
#include<iostream>
#include<algorithm>
using namespace std;
int a[5005][5005];
int dist[5005];
bool visit[5005];
int n, m;
int prim();
int main(void)
{
cin >> n >> m;
for (int i = 0; i < 5005; i++)
for (int j = 0; j < 5005; j++)
a[i][j] = 0x3f3f3f3f;
for (int i = 0; i < 5005; i++)
{
dist[i] = 0x3f3f3f3f;
visit[i] = false;
}
int x, y, z;
for (int i = 1; i <= m; i++)
{
cin >> x >> y >> z;
if (z < a[x][y]) a[x][y] = a[y][x] = z;
}
int sum=prim();
if (sum >= 0x3f3f3f3f) cout << "orz";
else cout << sum;
return 0;
}
int prim()
{
dist[1] = 0;
int temp;
int t = n;
int sum = 0;
while (t--)
{
temp = 0;
for (int i = 1; i <= n; i++)
{
if (!visit[i] && (temp == 0 || dist[i] < dist[temp]))
temp = i;
}
if (dist[temp] == 0x3f3f3f3f) return dist[temp];
visit[temp] = true;
sum += dist[temp];
for (int i = 1; i <= n; i++)
{
if (!visit[i]) dist[i] = min(dist[i], a[temp][i]);
}
}
return sum;
}