P r i m 算法 \color{red}{\huge{Prim算法}} Prim算法
P r i m Prim Prim算法一般就是用来求一个图的 最小生成树 \color{blue}{最小生成树} 最小生成树的。
最小生成树: \color{red}{最小生成树:} 最小生成树:在一个图中,①.连通所有的点,②.并且让所有边的权值总和最小。
集合内和集合外
\color{blue}{\huge{集合内和集合外}}
集合内和集合外:
所谓的集合内是指已经完成了更新放入到最后最小生成树中的节点,集合外是还在等待加入最小生成树的节点。
整体流程: \color{blue}{\huge{整体流程:}} 整体流程:
dist[i] <-- +∞
for(int i = 0 ; i < n ; i++)
{
找到集合外距离集合最近的点m;
t = m;
st[t] = true; //翻转一下标记变量,意为t已经加入到集合中
使用t去更新其他点到集合的距离
}
if(dist[t] == 0x3f3f3f3f)
return 0x3f3f3f3f;
for(int j = 1 ; j <= n ; j++)
dist[j] = min(dist[j],g[t][j]);
遍历每一个点进行更新的时候,此时要注意 d i s t [ N ] dist[N] dist[N]数组的含义了,是指到集合最小的距离,所以 d i s t [ j ] dist[j] dist[j]的最终取值是在 d i s t [ j ] dist[j] dist[j]和 g [ t ] [ j ] g[t][j] g[t][j]之间来抉择。
#include
#include
#include
#include
using namespace std;
const int N = 510;
int n,m;
int g[N][N];
int dist[N]; //表示集合外面一个点到集合内部最短的距离
bool st[N];
int Prim()
{
memset(dist,0x3f,sizeof(dist)); //初始化dist数组
dist[1] = 0;
int res = 0;
for(int i = 0 ; i < n ; i++) //n个点循环一次确定好一个点将其加入集合
{
int t = -1; //用来存储集合外的到集合距离最短的点
for(int j = 1 ; j <= n ; j++) //寻找符合t条件的点
if(!st[j] && (t == -1 || dist[t] > dist[j]))
t = j;
if(dist[t] == 0x3f3f3f3f) //很有可能图不是连通图,这样就算是最近的点距离也是无穷大
return 0x3f3f3f3f;
res += dist[t]; //计算路径综合
st[t] = true; //表示这个点加入到了集合中
for(int j = 1 ; j <= n ; j++)
dist[j] = min(dist[j],g[t][j]); //最短距离更新
}
return res;
}
int main ()
{
cin >> n >> m;
memset(g,0x3f,sizeof(g));
while(m--)
{
int a,b,c;
cin >> a >> b >>c;
g[a][b] = g[b][a] = min(g[a][b],c); //可能有重边取最小值的边作为目标边
}
int t = Prim();
if(t == 0x3f3f3f3f)
puts("impossible");
else
cout << t << endl;
return 0;
}