对于一个边上具有权值的图来说,其边权值和最小的生成树叫做图G的最小生成树

求无向图最小生成树主要有prim和kruskal两种算法

1.prim

将点集V分成Va和Vb两部分,Va为已经连入生成树的点,Vb为没有连入的点,按照边的大小逐渐向Va中加点,直到Va中包含所有点,具体步骤,复杂度O(mlogn)

⑴.首先初始化生成树的权值为0,任选一点放入Va,其余点放入Vb

⑵.在Vb中找一点u,在Va中找一点v(其实v一直不变),使得uv间距离最短,并更新u所连边,这也就是为什么v不变的原因

⑶.重复步骤2,直到Vb中没有点为止

#include <queue>
#include <vector>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
const double INF=0x3f3f3f3f;
using namespace std;
double dis[],G[][];
int n,x[],y[],vis[];
double prim(int v){
int i,j,u;
double sum,tmp;
sum=;
memset(vis,,sizeof(vis));
for(i=;i<=n;i++)
dis[i]=G[v][i];
vis[v]=;
for(i=;i<n;i++){
u=v;
tmp=INF;
for(j=;j<=n;j++)
if(dis[j]<tmp&&vis[j]==){
tmp=dis[j];
u=j;
} //找出与v相连最小的边
sum+=tmp;
vis[u]=;
for(j=;j<=n;j++)
if(!vis[j]){
if(dis[j]>G[u][j])
dis[j]=G[u][j];
} //更新与u相连的边的权值
}
return sum;
}
int main(){
int i,j;
double ans;
scanf("%d",&n);
for(i=;i<=n;i++)
scanf("%d%d",&x[i],&y[i]);
for(i=;i<=n;i++)
for(j=;j<=n;j++)
G[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
ans=prim(); //通过每个点的坐标算出每个点间距离
printf("%.2lf\n",ans);
return ;
}

2.kruskal

基于贪心的思想逐渐加入边并判断是否形成环,复杂度O(mlogm)

⑴.初始化,并将E进行排序

⑵.不断将边加入图中,并判断是否形成环

⑶.判断选择的边是否是n-1,并计算步骤2的权值和

#include <queue>
#include <vector>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
int V,E;
int par[],ran[],vis[];
void init(int n){
int i;
for(i=;i<=n;i++){
ran[i]=;
par[i]=i;
}
}
int find(int x){
if(par[x]==x)
return x;
return par[x]=find(par[x]);
}
void unite(int x,int y){
x=find(x);
y=find(y);
if(x==y)
return;
if(ran[x]<ran[y])
par[x]=y;
else{
par[y]=x;
if(ran[x]==ran[y])
ran[x]++;
}
}
bool same(int x,int y){
return find(x)==find(y);
} //并查集判断是否有环
struct node{
int u,v,cost;
};
bool cmp(node a,node b){
return a.cost<b.cost;
}
node es[];
int kruskal(){
int i;
int res=;
init(V);
sort(es,es+E,cmp);
for(i=;i<E;i++){
node e=es[i];
if(!same(e.u,e.v)){
unite(e.u,e.v);
res+=e.cost;
}
}
return res;
}
int main(){
int i;
scanf("%d%d",&V,&E);
memset(vis,,sizeof(vis));
for(i=;i<E;i++)
scanf("%d%d%d",&es[i].u,&es[i].v,&es[i].cost);
printf("%d\n",kruskal());
return ;
}

3.次小生成树

基于最小生成树的算法演变出次小生成树,其实基本的思想就是连入一条不在最小生成树上的边,从而形成一个环,去掉在环中并且在最小生成树上最大的边,遍历所有不在最小生成树上的边并进行同样的操作最小值即为次小生成树,简单证明就是连入一条边后去掉一个最大值相当于比原来的值增加的值最小(增加量=添加的边-环上的某一条边(并且这条边在最小生成树上),添加的边的权值一定,因此使环上的边最大),因次去掉最大的边,kruskal的复杂度是O(mlogm),求出环上的最大值复杂度是O(n*n),因此次小生成树的复杂度是O(mlogm+n*n)

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
const double INF=0x3f3f3f3f;
using namespace std;
int dis[],path[][],G[][];
int n,m,pre[],vis[],used[][];
int prim(int v){
int i,j,u,sum,tmp;
sum=;
memset(vis,,sizeof(vis));
memset(used,,sizeof(used));
memset(path,,sizeof(path));
for(i=;i<=n;i++){
dis[i]=G[v][i];
pre[i]=;
}
vis[v]=;
for(i=;i<n;i++){
u=v;
tmp=INF;
for(j=;j<=n;j++)
if(dis[j]<tmp&&vis[j]==){
tmp=dis[j];
u=j;
}
sum+=tmp;
vis[u]=;
used[u][pre[u]]=used[pre[u]][u]=;
for(j=;j<=n;j++){
if(vis[j]&&j!=u) //从j到父节点上的边的最大值和最小生成树上的边之间求最大值
path[u][j]=path[j][u]=max(path[j][pre[u]],dis[u]);
if(!vis[j]){ //与dp有些类似
if(dis[j]>G[u][j]){
dis[j]=G[u][j];
pre[j]=u;
}
}
}
}
return sum;
}
int second_prim(int tmp){
int i,j,ans;
ans=INF;
for(i=;i<=n;i++)
for(j=;j<=n;j++){
if(i!=j&&used[i][j]==)
ans=min(ans,tmp+G[i][j]-path[i][j]);
} //遍历每条边求次小生成树
return ans;
}
int main(){
int i,j,x,y,z,ans,tmp;
scanf("%d%d",&n,&m);
memset(G,INF,sizeof(G));
for(i=;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
G[x][y]=G[y][x]=z;
}
tmp=prim(); //先求出最小生成树
ans=second_prim(tmp);
printf("%d\n",ans);
return ;
}

BY  http://blog.csdn.net/stay_accept/article/details/50960185

最新文章

  1. WeakHashMap回收时机
  2. 明天去FDUSC报道了,GOD BLESS ALL OF US
  3. Windows注册表(持续更新)
  4. Fedora20的一些个人配置
  5. # HTML &amp;&amp; CSS 学习笔记
  6. 推荐7款新鲜出炉的HTML5/CSS3应用
  7. CF Tanya and Postcard
  8. Dev ComboxTree的实现
  9. javascript 基础1第11节
  10. java数据类型学习
  11. angularjs中{{}} 加载出现闪烁问题
  12. annotation 不给提示
  13. int *p[4]与int (*q)[4]的区别
  14. Flask分页
  15. Dynamics CRM2013 任务列表添加自定义按钮
  16. Android 音视频开发(五):使用 MediaExtractor 和 MediaMuxer API 解析和封装 mp4 文件
  17. 一脸懵逼学习Struts数据校验以及数据回显,模型驱动,防止表单重复提交的应用。
  18. C++学习札记(3)
  19. Spring Boot + Spring Cloud 实现权限管理系统 后端篇(十六):容器部署项目
  20. Visual Studio使用Web Deploy远程发布网站及其配置

热门文章

  1. 【转】利用匿名namespace解决C++中重复定义的问题
  2. S03_CH09_DMA_4_Video_Switch视频切换系统
  3. 解析Illumina+PacBio组装策略
  4. mysql cmd命令行 创建数据库 表 基础语句
  5. Django rest-framework框架-组件之分页
  6. 关于GPU的传输速度与什么有关??
  7. Django路由及函数视图
  8. linux命令安装docker
  9. Java基础加强-jdk1.5的一些新特性
  10. 【Hibernate】持久化对象状态及以及缓存