次小生成树
来源:互联网 发布:没有c基础可以学java吗 编辑:程序博客网 时间:2024/05/17 21:11
次小生成树的思想就是在最小生成树的基础上,去掉最小生成树中的一条边,在加入不在最先生成树中的一条边,并对重新生成的生成树选取权值最小的生成树,即为次小生成树。
次小生成树的主要思路就是在prim算法求最小生成树的过程中,标记mmax[u][v]区间中的最大权值的边,可以这么理解
假设此时u到v的边已经在最小生成树中,mmax[u][v]存储的就是在这些从u到v 的边中权值最大的边,即为边u到m 的权值,这样在求次小生成树的时候如果存在另外的map[u][v]的边就可以直接将边u到m的边去除,并加入map[u][m]边得到此下生成树。在得到最小生成树之后,需要对没有加入的所有边进行检索并建立新的生成树。
如果还是不懂可以看一看这个博客,很好的,http://www.cnblogs.com/hxsyl/p/3290832.html
次小生成树的模板如下:(实际上是poj1679的代码)
#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;}
代码如下
#include<iostream>#include <cstdio>#include <cstring>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); int second_strr[110]; while(tc--) { scanf("%d %d",&n,&m); memset(g,INF,sizeof(g)); memset(connect,false,sizeof(connect)); memset(second_strr,0,sizeof(second_strr)); //int k =0; 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; int min_mst = INF; //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(min_mst>mst+g[i][j]-mmax[i][j]) //求次小生成树 min_mst = mst+g[i][j]-mmax[i][j]; } printf("mst>>>>%d\n",mst); printf("min_mst>>%d\n",min_mst); } return 0;}/*16 81 2 32 3 41 3 51 4 63 4 53 5 64 5 75 6 7*/
0 0
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- 次小生成树
- chrome hosts文件管理工具 空白问题的解决
- 【总结】Effective java经验之谈,泛型
- POJ 1837 Balance(动态规划之背包问题)
- block的学习心得
- Spark Standalone 以及 HDFS系统环境搭建
- 次小生成树
- poj 3784 Running Median/sbt
- ListView--1 之 LayoutInfLayout源码分析
- 在Java程序中调用Salesforce REST API
- Anniversary party(树形DP入门)
- http-equiv是什么意思(转载)
- 实例讲解OSGI开发
- FZU2185 树的路径覆盖
- Uncaught RangeError: Invalid string length