图论总结(8)最小生成树

来源:互联网 发布:情义我心知国语版 编辑:程序博客网 时间:2024/06/10 11:23

最小生成树就是给你一个n个点的带权图,连了很多边,我们都知道连接n个点至少要n-1条边,这时图就变成了树,问你最少的权值和为多少。

下面给出两种算法,个人偏好第二种

一.prim算法

prim算法是基于贪心法来求的最小生成树。

vis数组表示是否已经进入最小生成树,min(u)数组表示为进树的点u离树上的点的最小距离。

模板:

#include<iostream> #include<cstring>using namespace std;int w[maxn][maxn];int minn[maxn];int vis[maxn];int main(){cin>>n;for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)cin>>w[i][j];memset(minn,127/3,sizeof(minn));minn[1]=0;memset(vis,0,sizeof(vis));for(int i=1;i<=n;i++){int k=0;for(int j=1;j<=n;j++){if(!vis[j]&&minn[j]<minn[k])k=j;}vis[k]=1;for(int j=1;j<=n;j++)if(!vis[j]&&w[k][j]<minn[j]){minn[j]=w[k][j];}}int tot=0;for(int i=1;i<=n;i++)tot+=minn[i];cout<<tot<<endl;return 0;}

二.Kruskal算法

先给所有边排序,若边连接的两点是不同集合(用并查集来判断),这选择该边。

模板:

int w[maxn],r[maxn],u[maxn],v[maxn];int father[maxn];int n,m;int find(int x){if(x!=father[x])father[x]=find(father[x]);return father[x];}bool cmp(const int i,const int j){return w[i]<w[j];}int Kluskal(){int ans=0;for(int i=1;i<=n;i++)father[i]=i;for(int i=1;i<=m;i++)r[i]=i;sort(r+1,r+m+1,cmp);for(int i=1;i<=m;i++){int e=r[i];int x=find(v[e]);int y=find(u[e]);if(x==y)continue;ans+=w[e];father[y]=x;}return ans;


原创粉丝点击