最小生成树(prim&&kruskal)
2018-03-07 12:04
302 查看
下面介绍两种求最小生成树算法
1.Kruskal算法
此算法可以称为“加边法”,初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里。
1. 把图中的所有边按代价从小到大排序;
2. 把图中的n个顶点看成独立的n棵树组成的森林;
3. 按权值从小到大选择边,所选的边连接的两个顶点ui,vi。ui,vi,应属于两颗不同的树,则成为最小生成树的一条边,并将这两颗树合并作为一颗树。
4. 重复(3),直到所有顶点都在一颗树内或者有n-1条边为止。
Code:
2.Prim算法
此算法可以称为“加点法”,每次迭代选择代价最小的边对应的点,加入到最小生成树中。算法从某一个顶点s开始,逐渐长大覆盖整个连通网的所有顶点。
图的所有顶点集合为V;初始令集合u={s},v=V−u={s};
在两个集合u,v能够组成的边中,选择一条代价最小的边(u,v),加入到最小生成树中,并把u0,v0并入到集合u中。
重复上述步骤,直到最小生成树有n-1条边或者n个顶点为止。
由于不断向集合u中加点,所以最小代价边必须同步更新;需要建立一个辅助数组用来维护集合v中每个顶点与集合u中最小代价边信息:
Code:#include<bits/stdc++.h>
#define N 200005
#define INF 0x3fffffff
using namespace std;
int flag
,f[5005][5005],k
;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
memset(flag,false,sizeof(flag));
memset(f,0x3f,sizeof(f));
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
flag[x]=true;flag[y]=true;
if(z<f[x][y])f[x][y]=f[y][x]=z;
}
for(int i=1;i<=n;i++)
if(!flag)
{
puts("orz");
return 0;
}
for(int i=1;i<=n;i++)k[i]=f[1][i];
k[1]=0;int ans=0;
for(int i=1;i<n;
d6ff
i++)
{
int Min=INF,p;
for(int j=1;j<=n;j++)
if(k[j]&&k[j]<Min)
{
Min=k[j];
p=j;
}
k[p]=0;
ans+=Min;
for(int j=1;j<=n;j++)
k[j]=min(f[p][j],k[j]);
}
printf("%d\n",ans);
}
1.Kruskal算法
此算法可以称为“加边法”,初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里。
1. 把图中的所有边按代价从小到大排序;
2. 把图中的n个顶点看成独立的n棵树组成的森林;
3. 按权值从小到大选择边,所选的边连接的两个顶点ui,vi。ui,vi,应属于两颗不同的树,则成为最小生成树的一条边,并将这两颗树合并作为一颗树。
4. 重复(3),直到所有顶点都在一颗树内或者有n-1条边为止。
Code:
#include<bits/stdc++.h> #define N 200005 using namespace std; int ans=0,f ,flag ; struct node { int x,y,z; }a ; int cmp(node x,node y) { return x.z<y.z; } int getfather(int x) { if(f[x]==x)return x;else f[x]=getfather(f[x]); return f[x]; } int main() { int n,m; scanf("%d%d",&n,&m); memset(flag,false,sizeof(flag)); for(int i=1;i<=m;i++) { scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); flag[a[i].x]=true;flag[a[i].y]=true; } for(int i=1;i<=n;i++) if(!flag) { puts("orz"); return 0; } sort(a+1,a+1+m,cmp); for(int i=1;i<=n;i++)f[i]=i; for(int i=1;i<=m;i++) { int x=a[i].x,y=a[i].y; x=getfather(x); y=getfather(y); if(x!=y) { ans+=a[i].z; f[y]=x; } } printf("%d",ans); return 0; }
2.Prim算法
此算法可以称为“加点法”,每次迭代选择代价最小的边对应的点,加入到最小生成树中。算法从某一个顶点s开始,逐渐长大覆盖整个连通网的所有顶点。
图的所有顶点集合为V;初始令集合u={s},v=V−u={s};
在两个集合u,v能够组成的边中,选择一条代价最小的边(u,v),加入到最小生成树中,并把u0,v0并入到集合u中。
重复上述步骤,直到最小生成树有n-1条边或者n个顶点为止。
由于不断向集合u中加点,所以最小代价边必须同步更新;需要建立一个辅助数组用来维护集合v中每个顶点与集合u中最小代价边信息:
Code:#include<bits/stdc++.h>
#define N 200005
#define INF 0x3fffffff
using namespace std;
int flag
,f[5005][5005],k
;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
memset(flag,false,sizeof(flag));
memset(f,0x3f,sizeof(f));
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
flag[x]=true;flag[y]=true;
if(z<f[x][y])f[x][y]=f[y][x]=z;
}
for(int i=1;i<=n;i++)
if(!flag)
{
puts("orz");
return 0;
}
for(int i=1;i<=n;i++)k[i]=f[1][i];
k[1]=0;int ans=0;
for(int i=1;i<n;
d6ff
i++)
{
int Min=INF,p;
for(int j=1;j<=n;j++)
if(k[j]&&k[j]<Min)
{
Min=k[j];
p=j;
}
k[p]=0;
ans+=Min;
for(int j=1;j<=n;j++)
k[j]=min(f[p][j],k[j]);
}
printf("%d\n",ans);
}
相关文章推荐
- 最小生成树(prim&kruskal)模板
- hdoj 1875 畅通工程再续【最小生成树 kruskal && prim】
- HDOJ 1102 Constructing Roads 最小生成树 kruskal && Prim
- hdoj 1233 还是畅通工程【最小生成树 kruskal && prim】
- HDOJ 1301 Jungle Roads 最小生成树 kruskal && prim
- 51Nod 1212 无向图最小生成树(最小生成树Kruskal & Prim
- 最小生成树 Kruskal&&Prim
- 最小生成树[Kruskal&&Prim](学习)
- HDOJ 1233 还是畅通工程 最小生成树 kruskal && prim
- POJ 1751 Highways 最小生成树 Kruskal && Prim
- ACM:最小生成树,kruskal && prim,并查集
- poj1861 最小生成树 prim & kruskal
- 算法记录---最小生成树【kruskal&&prim】
- Prim && Kruskal 生成MST(最小生成树)及最短路径问题
- 图论--最小生成树总结(Prim&&Kruskal)
- zoj 2966 Build The Electric System【最小生成树 Kruskal && prim】
- zoj 1586 QS Network【最小生成树 kruskal && prim】
- ZOJ 2048 Highways 最小生成树 Kruskal && Prim
- POJ 2075 Tangled in Cables 最小生成树 Kruskal && Prim
- POJ 2235 Frogger 最小生成树 Kruskal && Prim