我们学习最短路是为了解决某一个点到另一个点的最短距离,而最短路研究的一定是从某点到某点,我们计算出的是两点间的最短距离。
但是这里我们给出另一个问题,我们要求你求出当所有点连接起来时,最短的路径是多少?这个时候问题就变成了如何求出把所有点连接起来时的总路径;
我们思考这样一个问题,当我们要求得总体最短,也就是每个点都要找到距离他最短的点,那么每个点找到的一定是距离他最短距离的点;
然后把这个数值加入到我们的答案中即可;
看图:
例如这张图,在这里我们最开始把所有的点都初始化为了无穷大,然后把1的位置赋值为一,这样的话我们可以从一开始查找,每次我们都需要找到其他所有点,然后更新这个点的到集合的最短距离,然后把这个点加入到集合中;
代码如下:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int w[1010][1010],dist[1010];
bool st[1010];
int n,m;
void prim()
{
memset(st,0,sizeof st);//初始所有点都没有加入
memset(dist,0x3f,sizeof dist);//所有点都是距离无穷大;
dist[1]=0;//从这里开始遍历
for(int i=1;i<n;i++)
{
int t=-1;
for(int j=1;j<=n;j++)
if(!st[i]&&(t==-1||dist[t]>dist[j]))
t=j;//找到距离最短的那个点
st[t]=true;//加入我们的集合
for(int j=1;j<=n;j++)
{
if(!st[i])
dist[j]=min(dist[j],w[t][j]);//对所有点到集合距离更新
}
}
}
int main()
{
cin>>n>>m;
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
w[a][b]=w[b][a]=min(w[a][b],c);//这里多加一步对重边的特判,只要最短
}
prim();
int ans;//存储答案;这里保证了一定联通
for(int i=1;i<=n;i++)//就算不联通,加一层判断即可,最后的答案直接输出
ans+=dist[i];
cout<<ans;
}