• 图方法:二分无向图的联通子图查找


             连通域查找使用并行方法,需要对图片接触行列进行标签合并,连通域标签合并过程可以形式化为一个二分图。

             二分图又称作二部图,是图论中的一种特殊模型。 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),则称图G为一个二分图。

            寻找二分图的连通子图,用于解决传导等价类问题。


           

                                          图1  中有两个连通子图


    C++代码:

    	//输入为二部图的边集合,无重复
    	int findEqualSetBinGraph(
    		std::hash_multimap<int,int>  &equelHashL,
    		std::hash_multimap<int,int>  &equelHashR,
    		std::vector<int>  &vetexL,
    		std::vector<int>  &vetexR,
    		std::vector< std::pair<std::vector<int>,std::vector<int> > >  &equelSet,
    		bool bStack )
    	{
    
    		//使用堆栈,删除遍历过的边
    		if ( equelHashL.size() >0 )
    		{
    			std::stack<std::pair< int, int > > edgeEs;//使用边堆栈
    			std::stack< int >  pSL,pSR;//左边堆栈
    			std::vector< int >  pVL,pVR;//左右等价集合
    
    			for ( int i=0; i< vetexL.size();++i)
    			{//从左侧开始//遍历过的顶点边的个数为0
    				pVL.resize(0);
    				pVR.resize(0);
    				int VL = vetexL[i];
    				pSL.push(vetexL[i]);
    				pVL.push_back(VL);
    
    				while ( !pSL.empty() )
    				{
    					VL = pSL.top();
    					auto ptr =equelHashR.find(VL);
    					int C = equelHashR.count(VL);
    					if ( C> 0)
    					{
    						auto ptr1 =equelHashR.lower_bound(VL);
    						auto ptr2 =equelHashR.upper_bound(VL);
    
    						for (int i=0;i<C;++i)
    						{
    							pSR.push(ptr1->second);
    							pVR.push_back(ptr1->second);
    
    							++ptr1;
    						}
    						pSL.pop();
    
    						//去除掉相连的边
    						equelHashR.erase( VL );
    
    						//遍历对方的边
    						while ( !pSR.empty() )
    						{
    							int VR = pSR.top();
    							auto ptr =equelHashL.find(VR);
    							int C = equelHashL.count(VR);
    							if ( C > 1 )
    							{
    								auto ptr1 =equelHashL.lower_bound(VR);
    								auto ptr2 =equelHashL.upper_bound(VR);
    
    								for (int i=0;i<C;++i)//绕过第一个,必须要顺序排列才能使用
    								{
    									if ( ptr1->second != VL )
    									{
    										pSL.push(ptr1->second);
    										pVL.push_back( ptr1->second );
    
    										//删除右边元素
    										auto ptrR =equelHashR.lower_bound( ptr1->second );
    										for ( int i =0; i< equelHashR.count( ptr1->second ); ++i )
    										{
    											if ( ptrR->second == VR)
    											{
    												equelHashR.erase(ptrR);
    												break;
    											}
    											else
    											{
    												++ptrR;
    											}
    										}
    
    									}
    
    									++ptr1;
    								}
    								pSR.pop();
    								equelHashL.erase( VR );
    
    							}
    							else
    							{
    								//删除右边元素
    								int VR = pSR.top();
    								auto ptrR = equelHashL.lower_bound( VR );
    								for ( int i =0; i< equelHashL.count( VR ); ++i )
    								{
    									if ( ptrR->second == VL)
    									{
    										equelHashL.erase(ptrR);
    										break;
    									}
    									else
    									{
    										++ptrR;
    									}
    								}
    								pSR.pop();
    							}
    
    						}
    
    					} 
    					else
    					{
    						pSL.pop();
    					}
    
    
    				}
    
    				if ( pVL.size()>0 && pVR.size()>0 )
    				{
    					equelSet.push_back( std::make_pair( pVL,pVR ) );
    				}
    			}
    
    
    		}
    
    
    		return 1;
    	}
    
    	//输入为二部图的边集合,有重复
    	int findEqualSetBinGraph(
    		std::vector< std::pair<int,int>  >  &edgeSet,
    		std::vector< std::pair<std::vector<int>,std::vector<int> > > &equelSet,
    		bool bStack )
    	{
    
    		//4.2筛选集合//划分等价类//使用查找划分等价类
    		std::vector< std::pair<int,int> > equelLabelL,equelLabelR,equelLabelMin,equelLabelMinMirro;
    		equelLabelL.reserve(edgeSet.size() );
    		//等价集合
    		std::vector< std::pair<std::vector<int>,std::vector<int> > > equelSetL,equelSetR;//,equelSet,;
    
    		std::map<int,int>  equelMapL,equelMapR;//使用多值哈希//设置重复集合//用于最后合并连通域
    		std::hash_multimap<int,int>  equelHashL,equelHashR;
    		std::vector<int>  vetexL,vetexR;//顶点集合
    
    		if ( edgeSet.size()>0 )
    		{
    			std::qsort(&edgeSet[0],edgeSet.size(),sizeof(edgeSet[0]) ,cvWish::Operater::cmpPairIntFirst);
    
    			//使用基数排序//一次合并完成
    			{
    				int idxS =0;
    				int idxE =0;
    
    				int vL;
    				vL = edgeSet[0].first;
    				for ( idxE ; idxE< edgeSet.size();  ++idxE )
    				{
    					if ( idxE == 0 )
    					{
    						continue;
    					}
    					if ( vL == edgeSet[idxE].first ){
    					}
    					else
    					{
    						vL = edgeSet[idxE].first;
    						std::qsort(&edgeSet[idxS],idxE-idxS,sizeof(edgeSet[0]) ,cvWish::Operater::cmpPairIntSecond );
    						idxS = idxE;
    					}
    				}
    				std::qsort(&edgeSet[idxS],idxE-idxS,sizeof(edgeSet[0]) ,cvWish::Operater::cmpPairIntSecond );
    			}
    
    			equelLabelMin.reserve( edgeSet.size() );//equelLabelMin.reserve( equelLabelR.size() );
    			{
    				int vL,vR;
    				vL = edgeSet.begin()->first;
    				vR = edgeSet.begin()->second;
    				equelLabelMin.push_back( std::make_pair(vL,vR) );
    				for ( auto ptr = edgeSet.begin(); ptr!= edgeSet.end();  ++ptr)
    				{
    					if (ptr == edgeSet.begin())
    					{//跳过第一个
    						continue;
    					}
    					if ( vL == ptr->first && vR == ptr->second)
    					{
    					}
    					else
    					{
    						vL = ptr->first;
    						vR = ptr->second;
    						equelLabelMin.push_back(  std::make_pair(vL,vR) );
    					}
    					//vL = ptr->first;
    					//vR = ptr->second;
    				}
    			}
    
    			for ( auto ptr = equelLabelMin.begin(); ptr!= equelLabelMin.end();  ++ptr)
    			{
    				
    				equelHashR.insert( *ptr );
    				equelLabelMinMirro.push_back( std::make_pair( ptr->second,ptr->first ) );
    			}
    
    			std::qsort(&equelLabelMinMirro[0],equelLabelMinMirro.size(),sizeof(equelLabelMinMirro[0]) ,cvWish::Operater::cmpPairIntFirst );
    			
    			{
    				int idxS =0;
    				int idxE =0;
    				int vL   = equelLabelMinMirro[0].first;
    				for ( idxE ; idxE< equelLabelMinMirro.size();  ++idxE )
    				{
    					if ( idxE == 0 )
    					{
    						continue;
    					}
    					if ( vL == equelLabelMinMirro[idxE].first ){
    					}
    					else
    					{
    						vL = equelLabelMinMirro[idxE].first;
    						std::qsort(&equelLabelMinMirro[idxS],idxE-idxS,sizeof(equelLabelMinMirro[0]) ,cvWish::Operater::cmpPairIntSecond );
    						idxS = idxE;
    					}
    				}
    				std::qsort(&equelLabelMinMirro[idxS],idxE-idxS,sizeof(equelLabelMinMirro[0]) ,cvWish::Operater::cmpPairIntSecond );
    			}
    			for ( auto ptr = equelLabelMinMirro.begin(); ptr!= equelLabelMinMirro.end();  ++ptr)
    			{
    				equelHashL.insert(*ptr );//多值hash和多值map都不能剔除重复条目,不应该啊!
    			}
    
    			bool bStack = true;
    
    			//4.3 找出顶点集合//暂时不需要,根据所有的边找出顶点
    			vetexL.reserve(equelLabelMin.size());
    			{
    				int vL,vR;
    				vL = equelLabelMin.begin()->first;
    				vetexL.push_back(vL);
    				for (auto ptr = equelLabelMin.begin(); ptr!= equelLabelMin.end();++ptr)
    				{
    					if (ptr == equelLabelMin.begin())
    					{//跳过第一个
    						continue;
    					}
    					if ( vL == ptr->first ){
    					}
    					else
    					{
    						vL = ptr->first;
    						vetexL.push_back(vL);
    					}
    
    				}
    			}
    
    			vetexR.reserve( equelLabelMinMirro.size() );
    			{
    				int vL,vR;
    				vR = equelLabelMinMirro.begin()->first;
    				vetexR.push_back(vR);
    				for (auto ptr = equelLabelMinMirro.begin(); ptr!= equelLabelMinMirro.end();++ptr)
    				{
    					if ( ptr == equelLabelMinMirro.begin())
    					{//跳过第一个
    						continue;
    					}
    					if ( vR == ptr->first ){
    					}
    					else
    					{
    						vR = ptr->first;
    						vetexR.push_back(vR);
    					}
    
    				}
    			}
    
    		}
    
    		//使用堆栈法寻找连通子图
    		//边集合: equelLabelMin,equelLabelMinMirros,但使用equelHashL equelHashR 顶点集合: vetexL,vetexR
    		findEqualSetBinGraph(equelHashL,equelHashR,vetexL,vetexR,equelSet,bStack );
    
    		return 1;
    	}
    




  • 相关阅读:
    搭建DHCP服务
    sshd免密登陆
    加密类型以及数据加密解密过程
    搭建私有CA并实现证书颁发
    CentOS 7 启动流程
    Linux命令:tcpdump命令
    Linux命令:ping命令
    Linux命令:ss命令
    Linux命令:ip命令
    Linux命令:netstat命令
  • 原文地址:https://www.cnblogs.com/wishchin/p/9199985.html
Copyright © 2020-2023  润新知