对于一个边上具有权值的图来说,其边权值和最小的生成树叫做图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. 训练指南 UVALive - 5713(最小生成树 + 次小生成树)

    layout: post title: 训练指南 UVALive - 5713(最小生成树 + 次小生成树) author: "luowentaoaa" catalog: true ...

  2. [ An Ac a Day ^_^ ] [kuangbin带你飞]专题八 生成树 UVA 10600 ACM Contest and Blackout 最小生成树+次小生成树

    题意就是求最小生成树和次小生成树 #include<cstdio> #include<iostream> #include<algorithm> #include& ...

  3. URAL 1416 Confidential (最小生成树+次小生成树)

    Description Zaphod Beeblebrox - President of the Imperial Galactic Government. And by chance he is a ...

  4. POJ 1679 The Unique MST 【最小生成树/次小生成树模板】

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 22668   Accepted: 8038 D ...

  5. 最小生成树(次小生成树)(最小生成树不唯一) 模板:Kruskal算法和 Prim算法

    Kruskal模板:按照边权排序,开始从最小边生成树 #include<algorithm> #include<stdio.h> #include<string.h> ...

  6. HDU 4081 Qin Shi Huang&#39;s National Road System(最小生成树/次小生成树)

    题目链接:传送门 题意: 有n坐城市,知道每坐城市的坐标和人口.如今要在全部城市之间修路,保证每一个城市都能相连,而且保证A/B 最大.全部路径的花费和最小,A是某条路i两端城市人口的和,B表示除路i ...

  7. (最小生成树 次小生成树)The Unique MST -- POJ -- 1679

    链接: http://poj.org/problem?id=1679 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=82831#probl ...

  8. POJ 1679 The Unique MST (次小生成树)

    题目链接:http://poj.org/problem?id=1679 有t组数据,给你n个点,m条边,求是否存在相同权值的最小生成树(次小生成树的权值大小等于最小生成树). 先求出最小生成树的大小, ...

  9. URAL 1416 Confidential --最小生成树与次小生成树

    题意:求一幅无向图的最小生成树与最小生成树,不存在输出-1 解法:用Kruskal求最小生成树,标记用过的边.求次小生成树时,依次枚举用过的边,将其去除后再求最小生成树,得出所有情况下的最小的生成树就 ...

随机推荐

  1. 【规律】Cunning Friends

    Cunning Friends 题目描述 Anthony and his friends Ben and Chris decided to play a game. They have N piles ...

  2. 一个农民工自学java找到工作的励志故事

    <!-----------------------------------------------------------------------------摘自网络-------------- ...

  3. sys.dm_exec_query_stats的total_worker_time的单位是微秒还是毫秒

    该视图sys.dm_exec_query_stats存放的就是当前所有执行计划的详细信息,比如某条执行计划共占CPU多少等等.因为该视图对编译次数.占用CPU资源总量.执行次数等都进行了详细的记录,所 ...

  4. Tomcat服务器的数字证书 HTTPS 连接!

    SUN公司提供了制作证书的工具keytool, 在JDK 1.4以后的版本中都包含了这一工具,它的位置为\bin\keytool.exe 注意要使用一下 cmd命令,请确认jdk环境变量可以使用,可以 ...

  5. POJ1065(Wooden Sticks)--贪心

    木棍 时间限制: 1000MS   内存限制: 10000K 提交总数: 27336   接受: 11857 描述 有一堆木棍.每根杆的长度和重量是预先已知的.这些木棍将由木工机器逐一加工.它需要一些 ...

  6. C++线程同步之原子操作

    所谓的原子操作就是指一个线程对于某一个资源做操作的时候能够保证没有其它的线程能够对此资源进行访问. 原子操作仅仅能够解决某一个变量的问题,只能使得一个整型数据做简单算术运算的时候是原子的. 以下案例需 ...

  7. selenium重定向新窗口

    1.跳转新窗口 # 浏览器跳转新窗口后,selenium绑定新窗口 print('页面跳转后重新绑定selenium.') time.sleep(3) search_window = driver.c ...

  8. APP中的第三方“支付”功能测试建议

    目前市场上APP中带有支付功能的产品有非常多,那么APP中带有第三方支付功能的产品在这一模块该如何测试才尽可能的确保测试完整性. 正常流程: 正常使用支付宝.微信.银行卡(目前使用最多的第三方支付方式 ...

  9. Django drf:分页器详解

    一.简单分页(查看第n页,每页显示N条) 二.偏移分页(在第n个位置,向后查看n条数据) 三.CursorPagination(加密分页,只能看上一页和下一页,速度快) 一.简单分页(查看第n页,每页 ...

  10. rsync & sersync 实时同步

    1.根据之前一篇关于rsync的随笔部署好rsync服务后,可以开始inotify的部署 2.sersync的部署 ①.部署服务(安装和配置过程) #Master 部署Sersync服务 mkdir ...