Sollin算法可以看作是Kruskal算法和Prim算法的综合

基本思想是:

1. 从所有节点都孤立的森林开始,通过合并树来得到最小生成树

2. 每次合并树的边都是用最小权重的割边





程序具体实现思路:

初始化,update所有点(update函数只在开始处使用一次,以后就不用了)(update的具体操作类似于prim算法里的update)

循环一:找最小割边(FindMin)

循环二:1.根据每棵树都的最小割边进行合并

2.V[gen]中删除S[gen_other]中的所有元素

3.S[gen]中增加S[gen_other]中的所有元素

4.更新d值,在V[gen]中比较d[gen][i]和d[gen_other][i],取小值



和prim算法相比,这里的V和S都是有维度的,还有d也从一维变成了二维,增加的维度是对每棵树的标示





我用C++实现的Sollin算法源程序如下:

(1)common.h 主要是程序的头文件

(2)sollin.cpp 图的创建和算法启动点

(3)resources.h 图类、边类、点类,其中图类中包含了整个程序的核心部分

(1)common.h

#define _COMMON_H_
#include <map>
#include <vector>
#include <list>
#include <set>
#include <cstdio>
using namespace std;
#include <iostream>
#include <stdio.h>
#include <algorithm>
#define INF 10000
#define N 5
#endif

(2)sollin.cpp

#include "resources.h"

CEdge::CEdge(int a, int b, int c, int d){
tail=a;
head=b;
weight=c;
capacity=d;
} CEdge::CEdge(int a, int b, int c){
head=b;
tail=a;
weight=c;
} CEdge::CEdge(CEdge & x){
tail=x.getTail();
head=x.getHead();
weight=x.getWeight();
capacity=x.getCap();
} CGraph::CGraph(list<CEdge*> listEdge){
IncidentList=listEdge;
numVertex=N;
numEdge=listEdge.size();
} void main()
{
list<CEdge*> listEdge; CEdge* e1= new CEdge(1,2,35,10);
CEdge* e2= new CEdge(1,3,40,10);
CEdge* e3= new CEdge(2,3,25,10);
CEdge* e4= new CEdge(2,4,10,10);
CEdge* e5= new CEdge(3,4,20,10);
CEdge* e6= new CEdge(3,5,15,10);
CEdge* e7= new CEdge(4,5,30,10); CEdge* e8= new CEdge(2,1,35,10);
CEdge* e9= new CEdge(3,1,40,10);
CEdge* e10= new CEdge(3,2,25,10);
CEdge* e11= new CEdge(4,2,10,10);
CEdge* e12= new CEdge(4,3,20,10);
CEdge* e13= new CEdge(5,3,15,10);
CEdge* e14= new CEdge(5,4,30,10); listEdge.push_back(e1);
listEdge.push_back(e2);
listEdge.push_back(e3);
listEdge.push_back(e4);
listEdge.push_back(e5);
listEdge.push_back(e6);
listEdge.push_back(e7); listEdge.push_back(e8);
listEdge.push_back(e9);
listEdge.push_back(e10);
listEdge.push_back(e11);
listEdge.push_back(e12);
listEdge.push_back(e13);
listEdge.push_back(e14); CGraph g(listEdge);
g.p3();
g.p4();
g.solin();
getchar();
}

(3)resources.h

#include "common.h"

int set1[110]={0};

int FindSet(int x)
{
if(x==set1[x])
return x;
else
return set1[x]=FindSet(set1[x]);
} void UnionSet(int x, int y)
{
int fx=FindSet(x);
int fy=FindSet(y);
set1[fy]=fx;
} class CEdge{
private:
int tail, head;
int weight, capacity;
public:
CEdge(int a, int b, int c, int d);
CEdge(int a, int b, int c);
CEdge(CEdge &x);
int getHead(){return head;}
int getTail(){return tail;}
int getWeight(){return weight;}
int getCap(){return capacity;} }; bool cmp(CEdge* a, CEdge* b)
{
if(a->getWeight()<b->getWeight())
return 1;
else
return 0;
} class CGraph{
private:
int numVertex;
int numEdge;
list<CEdge*> IncidentList;
public:
CGraph(char* inputFile);
CGraph(list<CEdge*> listEdge);
CGraph(CGraph &);
map<int,list<CEdge*>> nelist;
vector<vector<CEdge*>> adjmatrix;
int d[N+10][N+10];
set<int> S[N+10];//被永久标记的点集
set<int> V[N+10];//初始点集 int getNumVertex(){
return numVertex;
}
int getNumEdge(){
return numEdge;
}
void p3(){
list<CEdge*>::iterator it,iend;
iend=IncidentList.end();
CEdge* emptyedge=new CEdge(-1,-1,-1,-1);
for(int i=0;i<=numVertex;i++)
{
vector<CEdge*> vec;
for(int j=0;j<=numVertex;j++)
{
vec.push_back(emptyedge);
}
adjmatrix.push_back(vec);
}
for(it=IncidentList.begin();it!=iend;it++){
adjmatrix[(*it)->getTail()][(*it)->getHead()] = *it ; }
} void p4(){
list<CEdge*>::iterator it,iend;
iend=IncidentList.end(); for(it=IncidentList.begin();it!=iend;it++)
nelist[(*it)->getTail()].push_back(*it); list<CEdge*>::iterator it2,iend2;
iend2=nelist[3].end();
} void Update(int k, int i){
list<CEdge*>::iterator it,iend;
it=nelist[i].begin();
iend=nelist[i].end();
for(;it!=iend;it++)
if((*it)->getWeight()<d[k][(*it)->getHead()]){
d[k][(*it)->getHead()]=(*it)->getWeight();
}
} int FindMin(int k){
set<int>::iterator vi,vend;
vend=V[k].end();
int mini=10000000;
int loc=0;
for(vi=V[k].begin();vi!=vend;vi++)
if(mini>=d[k][*vi])
{mini=d[k][*vi];loc=*vi;}
return loc;
} void solin(){
printf("sollin:\n");
for(int i=1;i<=N;i++)
set1[i]=i;
list<CEdge*> T;
int e[N+10];
//初始化操作
int j,k;
for(k=1;k<=N;k++)
for(j=1;j<=N;j++){
V[k].insert(j);
d[k][j]=INF;
} for(k=1;k<=N;k++){
S[k].insert(k);
V[k].erase(k);
d[k][k]=0;
Update(k,k);
} while(T.size()<(N-1))
{
for(int i=1;i<=N;i++)
{
if(i!=FindSet(i)) continue;
e[i]=FindMin(i);
}//1 for 查找N(k)与V–N(k)之间的最小割边 for(int i=1;i<=N;i++)
{
if(i!=FindSet(i)) continue;
if(FindSet(e[i])!=FindSet(i))
{
UnionSet(e[i],i);//合并树
//V[gen]中删除S[gen_other]中的所有元素
//S[gen]中增加S[gen_other]中的所有元素
int gen,gen_other;
gen=FindSet(i);
if(gen==i) gen_other=e[i];
else gen_other=i;
set<int>::iterator it,iend;
iend=S[gen_other].end();
for(it=S[gen_other].begin();it!=iend;it++){
V[gen].erase(*it);
S[gen].insert(*it);
}
//更新d值,在V[gen]中比较d[gen][i]和d[gen_other][i],取小值
iend=V[gen].end();
for(it=V[gen].begin();it!=iend;it++)
if(d[gen][*it]>d[gen_other][*it])
d[gen][*it]=d[gen_other][*it];
T.push_back(adjmatrix[e[i]][i]);
printf("%d---%d\n",e[i],i);
}
}//2 for 合并两棵树
}//while循环
}//sollin算法
};//graph类

Sollin算法的C++实现 BY gremount的更多相关文章

  1. Borůvka (Sollin) 算法求 MST 最小生成树

    基本思路: 用定点数组记录每个子树的最近邻居. 对于每一条边进行处理: 如果这条边连成的两个顶点同属于一个集合,则不处理,否则检测这条边连接的两个子树,如果是连接这两个子树的最小边,则更新 (合并). ...

  2. ACM主要算法

    ACM主要算法ACM主要算法介绍 初期篇 一.基本算法(1)枚举(poj1753, poj2965)(2)贪心(poj1328, poj2109, poj2586)(3)递归和分治法(4)递推(5)构 ...

  3. ACM常用算法

    数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平衡二叉树 二叉排序树 线段树 一维线段树 二维 ...

  4. ACM需要掌握算法

    数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平衡二叉树 二叉排序树 线段树 一维线段树 二维 ...

  5. ACM用到的算法。先做个笔记,记一下

    ACM 所有算法 数据结构 栈,队列,链表 哈希表,哈希数组 堆,优先队列 双端队列 可并堆 左偏堆 二叉查找树 Treap 伸展树 并查集 集合计数问题 二分图的识别 平衡二叉树 二叉排序树 线段树 ...

  6. ACM算法目录

    数据结构 栈,队列,链表 •哈希表,哈希数组 •堆,优先队列 双端队列 可并堆 左偏堆 •二叉查找树 Treap 伸展树 •并查集 集合计数问题 二分图的识别 •平衡二叉树 •二叉排序树 •线段树 一 ...

  7. ACM技能表

    看看就好了(滑稽) 数据结构 栈 栈 单调栈 队列 一般队列 优先队列/单调队列 循环队列 双端队列 链表 一般链表 循环链表 双向链表 块状链表 十字链表 邻接表/邻接矩阵 邻接表 邻接多重表 Ha ...

  8. Radix Heap ---Dijkstra算法的优化 BY Gremount

    Radix Heap 算法是在Dijkstra的Dial实现的基础上,通过减少对桶的使用,来优化算法的时间复杂度: Dial 时间复杂度是O(m+nC)     -------C是最长的链路 Radi ...

  9. ACM算法整理(不断补充ing)

    动态规划 1.背包问题 (1)01背包 ,n) DFR(v,V,C[i]) F[v]=max(F[v],F[v-C[i]]+W[i]); } //初始化时 //若背包不一定装满F全初始化为0 //若装 ...

随机推荐

  1. 【转载】Session对象的作用以及常见属性

    Session对象是Asp.Net应用程序中非常重要的一个内置对象,Session是指用户从打开浏览器访问服务器到关闭浏览器之间的会话状态,在一个会话期间,服务器会自动分配一个标识SessionId. ...

  2. vue-cli项目开发运行时内存暴涨卡死电脑

    最近开发一个vue项目时遇到电脑卡死问题,突然间系统就非常卡,然后卡着卡着就死机了,鼠标也动不了了,只能冷启动.而且因为是突然卡死,没来得及打开任务管理器. 最开始以为是硬盘的问题,但是在卡死几次后, ...

  3. poi 生成word 表格,并向表格单元格中插入多个图片

    接这上一篇,导入数据,也要完整导出来.话不多说,直接上代码. 效果图 //根据实体对象 ,生成XWPFDocument public static XWPFDocument exportDataInf ...

  4. CentOS7.X版本系统的下载和安装

    一.下载CentOS镜像 1.打开浏览器输入centos.org 2.选择版本下载 3.进入下载页面选择下载版本的种子链接,在迅雷下载即可. 二安装CentOS系统 1.服务器开机,根据界面提示进入磁 ...

  5. STM32定时器配置(TIM1、TIM2、TIM3、TIM4、TIM5、TIM8)高级定时器+普通定时器,定时计数模式下总结

    文章结构: ——> 一.定时器基本介绍 ——> 二.普通定时器详细介绍TIM2-TIM5 ——> 三.定时器代码实例 一.定时器基本介绍  之前有用过野火的学习板上面讲解很详细,所以 ...

  6. Maven配置环境变量

    Windows: 1:新建系统M2_HOME变量,并把安装maven路径拷贝上去 ​ 2:配置path变量,并把maven路径拷贝上去,这次的maven路径到bin ​ 3:测试maven环境是否配置 ...

  7. P2002 消息扩散[SCC缩点]

    题目描述 有n个城市,中间有单向道路连接,消息会沿着道路扩散,现在给出n个城市及其之间的道路,问至少需要在几个城市发布消息才能让这所有n个城市都得到消息. 输入格式 第一行两个整数n,m表示n个城市, ...

  8. POJ 2155 Matrix[树状数组+差分]

    原题链接:https://vjudge.net/problem/POJ-2155 题目大意 给定 n* n 矩阵A,其元素为0或1. A [i][j] 表示第i行和第j列中的数字.最初全为0. 我们有 ...

  9. MySQL 空间数据 简单操作

    在做的项目中需要,自己绘制区域图形,并存储起来,后面还有更新的需要,存文件不方面,想到现在数据库都支持空间数据库. 现在用的就是 MySQL ,就继续用 MySQL 来存储.管理空间数据.下面就做一些 ...

  10. Android adb的一些用法

    adb查看包名/Activity名 adb shell "logcat | grep START" adb shell dumpsys activity | find “mFocu ...