最小生成树——prim以及Kruskal
最小生成树——prim以及Kruskal
n点m边
1关于prim算法/适用于稠密图
2关于Kruskal算法/适用于稀疏图 m 远小于n的平方的图称为稀疏图
prim原理:
对树中的点进行遍历,存点构成一个新图,每次找离新图最近的点加入新图。
- 每次加入点时更新可加入边的数量以及大小(将新加入的点带来的边视为可加入)
- 每次全遍历所有可以加入的边找最近点
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;
}
Kruskal原理:
对图的边进行存储,将边权值排序,然后从小到大将边加入新图中
- 用并查集维护。
Kruskal代码实现解释
- 从小到大遍历边,对于每个边进行find判断(并查集内容)
for(int i=1;i<=m;i++)
{
int x=find(a[i].x);
int y=find(a[i].to);
if(x!=y)
{
sum+=a[i].w;
fa[x]=y;
if(++ans==n-1)
{
break;
}
}
}
Kruskal板子
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
int to;
int x;
int w;
}a[200005];
int fa[20005];
bool cmp(node x,node y)
{
return x.w<y.w;
}
int find(int x)
{
while(x!=fa[x])
{
x=fa[x]=fa[fa[x]];
}
return x;
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>a[i].x>>a[i].to>>a[i].w;
}
for(int i=1;i<=n;i++)
{
fa[i]=i;
}
sort(a+1,a+1+m,cmp);
int sum=0;
int ans=0;
for(int i=1;i<=m;i++)
{
int x=find(a[i].x);
int y=find(a[i].to);
if(x!=y)
{
sum+=a[i].w;
fa[x]=y;
if(++ans==n-1)
{
break;
}
}
}
if(ans==n-1)
cout<<sum;
else
cout<<"orz";
return 0;
}

浙公网安备 33010602011771号