最小生成数——prim以及Kruskal
1.关于prim算法
2.关于Kruskal算法
-
原理
-
板子
-
板子题
prim原理:
对树中的点进行遍历,存点构成一个新图,每次找离新图最近的点加入新图。
代码实现解释
- 将起始点的一系列临边的点赋值
for(int i=head[1];i;i=a[i].next)
{
int k=a[i].to;
vi[k]=min(vi[k],a[i].w); //注意有重边
}
- 在所有点中找离当前图最近的点,并将最近点标记为now
for(int i=1;i<=n;i++)
{
if(!ans[i]&&ma>vi[i])
{
now=i;
ma=vi[i];
}
}
3.对now(新加入的点)的临边进行赋值
for(int i=head[now];i;i=a[i].next)
{
int k=a[i].to;
if(!ans[k]&&vi[k]>a[i].w)
{
vi[k]=a[i].w;
}
}
prim板子
#include<iostream>
#include<algorithm>
using namespace std;
int head[200005];
int cnt;
int b[200005];
int ans[200005];
int vi[200005];
struct node{
int next;
int to;
int w;
}a[400005];
void add(int x,int y,int w)
{
a[++cnt].next=head[x];
a[cnt].to=y;
a[cnt].w=w;
head[x]=cnt;
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
add(x,y,z);
add(y,x,z);
}
for(int i=2;i<=n;i++)
{
vi[i]=100000000;
}
for(int i=head[1];i;i=a[i].next)
{
int k=a[i].to;
vi[k]=min(vi[k],a[i].w); //注意有重边
}
int now=1;
int r=0;
int sum=0;
while(++r<n)
{
int ma=100000000;
ans[now]=1;
for(int i=1;i<=n;i++)
{
if(!ans[i]&&ma>vi[i])
{
now=i;
ma=vi[i];
}
}
if(ma==100000000)
{
cout<<"orz";
return 0;
}
sum+=ma;
for(int i=head[now];i;i=a[i].next)
{
int k=a[i].to;
if(!ans[k]&&vi[k]>a[i].w)
{
vi[k]=a[i].w;
}
}
}
cout<<sum;
return 0;
}
标签:cnt,prim,int,vi,Kruskal,最小,now,head
From: https://www.cnblogs.com/wl1917/p/18205171