zoukankan      html  css  js  c++  java
  • 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类
    




  • 相关阅读:
    开源项目
    [Accessibility] Missing contentDescription attribute on image [可取行]失踪contentDescription属性图像
    Android 布局 中实现适应屏幕大小及组件滚动
    EF 错误记录
    EasyUI 加载时需要显示和隐藏 panel(面板)内容破版问题
    IE 报表缩放后页面破版
    VS 2017 引入nuget 问题
    SSRS 报表显示页面 asp net session丢失或者找不到 asp net session has expired or could not be found()
    log4net 配置
    网站
  • 原文地址:https://www.cnblogs.com/gremount/p/5768011.html
Copyright © 2011-2022 走看看