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. JS权威指南读书笔记(二)

    第四章 表达式和运算符 1 new调用构造函数的过程     a 创建一个新的空对象     b 设置空对象的_proto_指向构造函数原型prototype     c 将这个新对象当做this的值 ...

  2. jQuery遍历(2)

    上期我们讲了遍历的祖先和后代的问题,现在我们讲讲遍历同胞 同胞拥有相同的父元素. 通过 jQuery,您能够在 DOM 树中遍历元素的同胞元素. jQuery siblings() 方法 siblin ...

  3. c# dynamic实现动态实体,不用定义实体就能序列化为标准json

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.D ...

  4. Qt QPushButton 背景色

    正常状态:黑底(背景色),白字(前景色),圆角,向外凸起 鼠标停留:背景和前景反色 鼠标按下:背景色变为淡蓝色,向内凹陷 ui->pushButton->setStyleSheet(&qu ...

  5. 修改docker容器端口映射的方法

    大家都知道docker run可以指定端口映射,但是容器一旦生成,就没有一个命令可以直接修改.通常间接的办法是,保存镜像,再创建一个新的容器,在创建时指定新的端口映射. 有没有办法不保存镜像而直接修改 ...

  6. DbTemplate

    package com.me.dbComponent; import java.sql.Connection; import java.sql.PreparedStatement; import ja ...

  7. Winserver-Exception from HRESULT: 0x800A03EC

    Q: 程序在VS中手动执行没问题,但是排了JOB报异常:Exception from HRESULT: 0x800A03EC   at Excel.WorkbookClass.SaveAs() A: ...

  8. Android笔记(二十) Activity中的跳转和值传递

    我们知道,一个APP是由若干个Activity组成的,那么各个Acitivity中肯定需要进行跳转以及传递数值以保证App的运行,现总结一下多个Activity之间的跳转和值传递. 显式Intent跳 ...

  9. djangoform表单使用验证码

    8.1.安装captcha 直接安装:pip install django-simple-captcha Django自动帮我们安装了相关的依赖库six.olefile和Pillow,其中的Pillo ...

  10. dt7.0自定义推送熊掌号功能插件

    因要推送较早的数据,所以写了一个自定义推送熊掌号的功能插件,因我自己站点是新站,推送的数据较少,所以程序比较简单,算是初始版本,凑合着用吧. <?php /* 百度当天主动推送熊掌功能 作者:6 ...