最小生成树和次小生成树
2014-03-31 22:51
288 查看
最小生成树和次小生成树定义:
生成树:图G的生成树包含原图中的全部顶点n,和n-1条边.
最小生成树就是所有生成树中边权和最小的.
2 那么如何求最小生成树呢?
介绍两种基于贪心的算法:
1.prim算法
设图G =(V,E),其生成树的顶点集合为U。
①、把v0放入U。
②、在所有u∈U,v∈V-U的边(u,v)∈E中找一条最小权值的边,加入生成树。
③、把②找到的边的v加入U集合。如果U集合已有n个元素,则结束,否则继续执行②。
2.kruskal算法
首先将所有边按边权排序,然后按照边权从小到大依次处理.这里要用到并查集的思想,假设已有点集U,现在正在处理边i->j,如果i,j已在
U中则处理下一条边,否则将i,j加入并查集中.继续处理下一条边,直到有n-1条边为止.
3 次小生成树
次小生成树可由最小生成树换一条边得到
算法:
1)先用prim求出最小生成树T,在prim的同时,用一个矩阵max[u][v]记录在树中连接u-v的路径中权值最大的边.
2)枚举所有不在T中的边u-v,加入边u-v,删除权值为max[u][v]的边,不断枚举找到次小生成树.
次小生成树的模板:
生成树:图G的生成树包含原图中的全部顶点n,和n-1条边.
最小生成树就是所有生成树中边权和最小的.
2 那么如何求最小生成树呢?
介绍两种基于贪心的算法:
1.prim算法
设图G =(V,E),其生成树的顶点集合为U。
①、把v0放入U。
②、在所有u∈U,v∈V-U的边(u,v)∈E中找一条最小权值的边,加入生成树。
③、把②找到的边的v加入U集合。如果U集合已有n个元素,则结束,否则继续执行②。
2.kruskal算法
首先将所有边按边权排序,然后按照边权从小到大依次处理.这里要用到并查集的思想,假设已有点集U,现在正在处理边i->j,如果i,j已在
U中则处理下一条边,否则将i,j加入并查集中.继续处理下一条边,直到有n-1条边为止.
3 次小生成树
次小生成树可由最小生成树换一条边得到
算法:
1)先用prim求出最小生成树T,在prim的同时,用一个矩阵max[u][v]记录在树中连接u-v的路径中权值最大的边.
2)枚举所有不在T中的边u-v,加入边u-v,删除权值为max[u][v]的边,不断枚举找到次小生成树.
次小生成树的模板:
#include<iostream> using namespace std; const int INF=0x3f3f3f3f; int g[110][110],dist[110],mmax[110][110]; int pre[110]; bool mark[110]; bool connect[110][110]; int mst,mint; int n,m; int prim() { int res=0,fa,p,min,i,j; memset(mmax,0,sizeof(mmax)); for(i=1;i<=n;i++) { dist[i]=g[1][i]; pre[i]=1; mark[i]=false; } dist[1]=0; mark[1]=true; for(i=1;i<n;i++) { p=-1;min=INF; for(j=1;j<=n;j++) { if(!mark[j]&&dist[j]<min) { p=j; min=dist[j]; } } if(p==-1) return res; mark[p]=true; res+=dist[p]; fa=pre[p]; connect[fa][p]=false; connect[p][fa]=false; mmax[fa][p]=min; for(j=1;j<=n;j++) mmax[j][p]=(mmax[fa][p]>mmax[j][fa])?mmax[fa][p]:mmax[j][fa]; for(j=1;j<=n;j++) { if(!mark[j]&&dist[j]>g[p][j]) { dist[j]=g[p][j]; pre[j]=p; } } } return res; } int main() { int tc; //freopen("1.txt","r",stdin); scanf("%d",&tc); while(tc--) { scanf("%d %d",&n,&m); memset(g,INF,sizeof(g)); memset(connect,false,sizeof(connect)); while(m--) { int u,v,c; scanf("%d %d %d",&u,&v,&c); g[u][v]=c; g[v][u]=c; connect[u][v]=true; connect[v][u]=true; } mst=prim(); int i,j; bool flag=false; for(i=1;i<=n;i++) for(j=1;j<=n;j++) { if(connect[i][j]==false||g[i][j]==INF) continue; if(g[i][j]==mmax[i][j]) { flag=true; break; } } if(flag) printf("Not Unique!\n"); else printf("%d\n",mst); } return 0; }
相关文章推荐
- java虚拟机和Dalvik虚拟机的区别
- iOS网络开发之:NSURLConnection
- TCP长连接与短连接
- [组图]又到年终报告时——年终报告PPT设计制作技巧分享
- 【转载】游戏场景设计、构图的一些基本思考
- Property List 文件
- 沙盒(二)
- 2014校园招聘回忆
- 搞ACM的你伤不起呀!
- 算法 拓扑排序
- ios何时使用self.
- [组图]乔布斯的演说秘籍——演说的高级技巧篇
- 易卡电子请柬网
- Spring或者JDBC读取配置文件连接
- 自编码器及相关变种算法简介
- 第五周上机实践项目——指向学生类的指针
- db2 索引,表结构查看的一些语句
- 基于MFC的OpenGL绘图
- Java笔记深解---static
- 算法导论学习总结-基础篇(一)