prim算法Kruskal算法

#include<bits/stdc++.h>
using namespace std;
#define ios                      \
    ios::sync_with_stdio(false); \
    cin.tie(0);                  \
    cout.tie(0);
struct road
{
	int t,l,next;
}edge[2*500000+100];
int head[100010];
int vis[100010];
int cnt=0;
void addedge(int a,int b,int v)
{
	edge[++cnt].t=b;
	edge[cnt].l=v;
	edge[cnt].next=head[a];
	head[a]=cnt;
}
struct ty2
{
	int x,dis;
	bool operator < (const ty2 &a)const 
	{
		return dis>a.dis;
	}
};
priority_queue<ty2>q;
void prim()
{
	int ans=0;
	vis[1]=1;
	ty2 tmp;
	for(int i=head[1];i!=-1;i=edge[i].next)
	{
		tmp.x=edge[i].t;
		tmp.dis=edge[i].l;
		q.push(tmp);
	}
	while(!q.empty())
	{
		ty2 tmp=q.top();
        q.pop();
		int x=tmp.x;
		if(vis[x]) continue;
		ans+=tmp.dis;
		vis[x]=1;
		for(int i=head[x];i!=-1;i=edge[i].next)
		{
			if(vis[edge[i].t]) continue;
			tmp.x=edge[i].t;
			tmp.dis=edge[i].l;
			q.push(tmp);
		}	
	}
	cout<<ans<<endl;
}
int main() 
{
	ios;
	int n,m;
	cin>>n>>m;
	memset(head,-1,sizeof(head));
	for(int i=1;i<=m;i++)
	{
		int a,b,v;
		cin>>a>>b>>v;
		addedge(a,b,v);
		addedge(b,a,v);
	}
	prim();
}

用len数组优化prim 牛客算法入门班第三节课

len数组的含义就是该点到这个已经生成的树的距离

其主要思想就是如果该点到已经生成的树的距离已经确定且小于从树上新拓展的边

则不需要进行入队操作

#include<bits/stdc++.h>
using namespace std;
#define ios                      \
    ios::sync_with_stdio(false); \
    cin.tie(0);                  \
    cout.tie(0);
struct road
{
	int t,l,next;
}edge[2*500000+100];
int head[100010];
int vis[100010];
int cnt=0;
void addedge(int a,int b,int v)
{
	edge[++cnt].t=b;
	edge[cnt].l=v;
	edge[cnt].next=head[a];
	head[a]=cnt;
}
struct ty2
{
	int x,dis;
	bool operator < (const ty2 &a)const 
	{
		return dis>a.dis;
	}
};
int len[100010]; 
priority_queue<ty2>q;
void prim()
{
	int ans=0;
	vis[1]=1;
	ty2 tmp;
	memset(len,0x7f,sizeof(len));
	for(int i=head[1];i!=-1;i=edge[i].next)
	{
		tmp.x=edge[i].t;
		tmp.dis=edge[i].l;
		len[tmp.x]=tmp.dis;
		q.push(tmp);
	}
	while(!q.empty())
	{
		ty2 tmp=q.top();
        q.pop();
		int x=tmp.x;
		if(vis[x]) continue;
		ans+=tmp.dis;
		vis[x]=1;
		for(int i=head[x];i!=-1;i=edge[i].next)
		{
			if(vis[edge[i].t]) continue;
			if(len[edge[i].t]>edge[i].l)
			{
				tmp.x=edge[i].t;
				len[edge[i].t]=tmp.dis=edge[i].l;
				q.push(tmp);
			}
		}	
	}
	cout<<ans<<endl;
}
int main() 
{
	ios;
	int n,m;
	cin>>n>>m;
	memset(head,-1,sizeof(head));
	for(int i=1;i<=m;i++)
	{
		int a,b,v;
		cin>>a>>b>>v;
		addedge(a,b,v);
		addedge(b,a,v);
	}
	prim();
}

prim应用的也是贪心每次找出到树上长度最小的边如果呢个边的点在树上则跳过否则加进来

与dijkstra的区别就是在贪心的时候贪心的东西不一样

Kruskal算法贪心把边从小到大进行排序

然后按边从小到大顺序看连接该边的两个点是否在同一个集合里面

在的话就直接进行连接

#include<bits/stdc++.h>
using namespace std;
int fa[100010];
int find(int x)
{
	return fa[x]=fa[x]==x?x:find(fa[x]);
}
struct road
{
	int x,y,z;
}edge[500010];
bool cmp(road A,road B)
{
	return A.z<B.z;
}
int main()
{
	int n,m;
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>edge[i].x>>edge[i].y>>edge[i].z;		
	}
	for(int i=1;i<=n;i++)
	{
		fa[i]=i;
	}
	sort(edge+1,edge+1+m,cmp);
	int ans=0;int cnt=0;
	for(int i=1;i<=m;i++)
	{
		int fx=find(edge[i].x);
		int fy=find(edge[i].y);
		if(fx==fy) continue;
		ans+=edge[i].z;
		fa[fx]=fy;
        cnt++;
        if(cnt>=n-1) break;
	}
	cout<<ans;
}

prim和kruskal的贪心策略是一样的都是选取耗费最小的边

对于prim,其选取的边(u,v)必有一个顶点已经被覆盖,另一个顶点未被覆盖

而对于kruskal,其选取的边(u,v)任意,只要这个边的加入不能使被覆盖的点构成回路

prim算法的时间复杂度为O((n+m)logm)-适用于稠密图

kruskal算法的时间复杂度为O(mlogm)-适用于稀疏图

现在的时间差距并不明显

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值