Sollin算法的C++实现 BY gremount

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:
");
		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
",e[i],i);
				}
			}//2 for 合并两棵树
		}//while循环
	}//sollin算法
};//graph类




原文地址:https://www.cnblogs.com/gremount/p/5768011.html