bool dfs_all_path(Digraph& dg, ArcFilter& arc_filter, Digraph::Node s, Digraph::Node t, IntArray& pathNums, EdgeArray& allPath) { for(int k=1;k<1000;k++) { //存储搜索的路径 EdgeArray p; //搜索第k路径 //acutPrintf(_T("\nK=%d"),k); if(!mrp_k(dg, arc_filter, s, t, k, p)) { //一旦第k次搜索不成功,后续的搜索同样也会失败! //所以这时候可以直接退出循环了 break; } else { //记录路径的分支个数 pathNums.push_back(p.size()); //将路径复制到allPath数组中 std::copy(p.begin(), p.end(), std::back_inserter(allPath)); } } return (!pathNums.empty()); //return false; }
//根据前向节点查找路径 static bool PathFromPred(Digraph& dg, Digraph::Node s, Digraph::Node t, PredMap& pred, EdgeArray& p) { EdgeArray pp; Digraph::Node u = t; while(pred[u] != INVALID) { Digraph::Node v = pred[u]; if(v != INVALID) { for(Digraph::InArcIt e(dg,u);e!=INVALID;++e) { if(dg.source(e) == v) { pp.push_back(e); } } } u = v; } if(u == s) { //得到的路径是反向的,需要逆转过来 GraphUtils::ReverseArray(pp); } p = pp; return (u == s); }
//根据前向节点查找路径 static bool PathFromPred(VentNetwork* vnet, Digraph::Node s, Digraph::Node t, PredMap& pred, EdgeArray& p) { EdgeArray pp; Digraph::Node u = t; while(pred[u] != INVALID) { Digraph::Node v = pred[u]; if(v != INVALID) { for(Digraph::InArcIt e(vnet->graph(),u);e!=INVALID;++e) { if(vnet->graph().source(e) == v) { pp.push_back(e); } } } u = v; } if(u == s) { //得到的路径是反向的,需要逆转过来 GraphUtils::ReverseArray(pp); //过滤虚拟分支 vnet->filterVirutalEdges(pp, p); } return (u == s); }
// 使用宽度优先搜索BFS计算最短距离 static void SortAirEdges( Digraph& dg, ArcFilter& ef, Digraph::Node s, Digraph::Node t, const EdgeArray& airEdges, EdgeArray& es ) { AFGraph afg( dg, ef ); Bfs<AFGraph> aBfs( afg ); aBfs.run( s ); //if(!aDfs.reached(t)) return; // s->t不可达 typedef ReverseDigraph<AFGraph> RDigraph; RDigraph rdg( afg ); Bfs<RDigraph> bBfs( rdg ); bBfs.run( t ); //if(!bDfs.reached(s)) return; typedef std::vector<AirEdgeDist> AirEdgeArray; AirEdgeArray aes; int len = airEdges.length(); for( int i = 0; i < len; i++ ) { Digraph::Arc e = airEdges[i]; Digraph::Node u = dg.source( e ); Digraph::Node v = dg.target( e ); AirEdgeDist aed; aed.e = e; if( aBfs.reached( u ) ) { aed.sd = aBfs.dist( u ); } else { acutPrintf( _T( "\n第%d个用风地点【始点】不可达" ), i ); } if( bBfs.reached( v ) ) { aed.td = bBfs.dist( v ); } else { acutPrintf( _T( "\n第%d个用风地点【末点】不可达" ), i ); } aes.push_back( aed ); } // 降序排序 std::sort( aes.begin(), aes.end() ); for( AirEdgeArray::iterator itr = aes.begin(); itr != aes.end(); itr++ ) { es.append( itr->e ); } }
void PivotMDS::getPivotDistanceMatrix( const GraphAttributes& GA, Array<Array<double> >& pivDistMatrix) { const Graph& G = GA.constGraph(); const int n = G.numberOfNodes(); // lower the number of pivots if necessary int numberOfPivots = min(n, m_numberOfPivots); // number of pivots times n matrix used to store the graph distances pivDistMatrix.init(numberOfPivots); for (int i = 0; i < numberOfPivots; i++) { pivDistMatrix[i].init(n); } // edges costs array EdgeArray<double> edgeCosts; bool hasEdgeCosts = false; // already checked whether this attribute exists or not (see call method) if (m_hasEdgeCostsAttribute) { edgeCosts.init(G); for(edge e : G.edges) { edgeCosts[e] = GA.doubleWeight(e); } hasEdgeCosts = true; } // used for min-max strategy NodeArray<double> minDistances(G, std::numeric_limits<double>::infinity()); NodeArray<double> shortestPathSingleSource(G); // the current pivot node node pivNode = G.firstNode(); for (int i = 0; i < numberOfPivots; i++) { // get the shortest path from the currently processed pivot node to // all other nodes in the graph shortestPathSingleSource.fill(std::numeric_limits<double>::infinity()); if (hasEdgeCosts) { dijkstra_SPSS(pivNode, G, shortestPathSingleSource, edgeCosts); } else { bfs_SPSS(pivNode, G, shortestPathSingleSource, m_edgeCosts); } copySPSS(pivDistMatrix[i], shortestPathSingleSource); // update the pivot and the minDistances array ... to ensure the // correctness set minDistance of the pivot node to zero minDistances[pivNode] = 0; for(node v : G.nodes) { minDistances[v] = min(minDistances[v], shortestPathSingleSource[v]); if (minDistances[v] > minDistances[pivNode]) { pivNode = v; } } } }
void GenotypToR( Digraph& dg, EdgeArray& E, Binary::Binary* gen, VNR_EdgeMap& vnr_edge_map ) { assert( countArcs( dg ) == gen->variables.size() ); assert( E.size() == gen->variables.size() ); for( uint i = 0; i < E.size(); i++ ) { Digraph::Arc e = E[i]; vnr_edge_map[e].cr = gen->realValue.at( i ); if( vnr_edge_map[e].bInitR ) { vnr_edge_map[e].cr = vnr_edge_map[e].r; } } }
static void ILT_Helper( Digraph& dg, ILT_EdgeDataMap2& datas, ArcFilter& ef, NodeFilter& nf, EdgeArray& sortedAirEdges, IntMap& cmap ) { // 记录用风地点的始末搜索得到的count AcDbIntArray sAirs, tAirs; double st = Timer::rdtscSeconds(); // 显示排序后,用风地点的顺序编号 //DisplayAirEdgeNum(sortedAirEdges, datas); int len = sortedAirEdges.length(); acutPrintf( _T( "\n用风地点个数:%d" ), len ); for( int i = 0; i < len; i++ ) { Digraph::Arc e = sortedAirEdges[i]; Digraph::Node u = dg.source( e ); Digraph::Node v = dg.target( e ); sAirs.append( CountInFlowNodes( dg, ef, nf, u, cmap ) ); tAirs.append( CountOutFlowNodes( dg, ef, nf, v, cmap ) ); //acutPrintf(_T("\n第%d个用风地点【始节点】=%d 【末节点】=%d"), i, sAirs[i], tAirs[i]); } /*for(Digraph::NodeIt n(dg); n!=INVALID; ++n) { if(nf[n] && imap[n]==0) imap[n] = 1; }*/ double et = Timer::rdtscSeconds(); acutPrintf( _T( "\n第1次正反dfs查找耗费时间:%.5f" ), et - st ); // 显示分支的始末节点的cmap值(测试用) //DisplayEdgeCMapValue(dg, sortedAirEdges, datas, cmap, sAirs, tAirs); //assert(sAirs.length() == len); //assert(tAirs.length() == len); st = Timer::rdtscSeconds(); for( int i = len - 1; i >= 0; i-- ) { Digraph::Arc e = sortedAirEdges[i]; Digraph::Node u = dg.source( e ); Digraph::Node v = dg.target( e ); MinusInFlowNodes( dg, ef, nf, u, cmap, sAirs[i] ); PlusOutFlowNodes( dg, ef, nf, v, cmap, tAirs[i] ); } et = Timer::rdtscSeconds(); acutPrintf( _T( "\n第2次正反dfs查找耗费时间:%.5f" ), et - st ); /* * 处理完之后,可能出现一些分支的始节点(或末节点)的cmap=0 * 而末节点(或始节点)的cmap不等于0 * 这些分支中可能有部分分支也可视为主要进回风之间的联络巷 */ // 显示分支的始末节点的cmap值(测试用) //DisplayEdgeCMapValue(dg, sortedAirEdges, datas, cmap, sAirs, tAirs); }
void CPlanarSubClusteredST::call(const ClusterGraph &CG, EdgeArray<bool>& inST) { initialize(CG); inST.fill(false); //representationsgraphs for every cluster, on clustergraph ClusterArray<Graph*> l_clusterRepGraph(CG, 0); computeRepresentationGraphs(CG, l_clusterRepGraph); //now we compute the spanning trees on the representation graphs //we should save the selection info on the original edge //are statically on the repgraphedges (we only have edge -> repedge //information) but ClusterArray< EdgeArray<bool> > l_inTree(CG); cluster c; forall_clusters(c, CG) { l_inTree[c].init(*l_clusterRepGraph[c], false); //compute STs NodeArray<bool> visited(*l_clusterRepGraph[c], false); dfsBuildSpanningTree(l_clusterRepGraph[c]->firstNode(), l_inTree[c], visited); }//forallclusters
void Kruskal(EdgeArray& Q, int n){ _count = 0; DisjointSets D(n); EdgeArray E_T; int size = Q.getSize(); int i = 0; //Q.sort(); while( size != 0 && E_T.getSize() != n - 1 ) { _count++; Edge edge = Q[i]; if(edge.cost == INF) break; size--; if( D.find( edge.v ) != D.find( edge.w ) ) { _count++; D.merge( edge.v, edge.w ); E_T.append( edge.v, edge.w, edge.cost ); } i++; } _count += D.count; /*if( E_T.getSize() == n - 1 ) { _count++; E_T.printSimple(); } else { cout << "Failure!\n"; }*/ }
bool mrp_k(VentNetwork* vnet, ArcFilter& arc_filter, Digraph::Node s, Digraph::Node t, int k, EdgeArray& p) { //如果始节点的值"无效"(INVALID),那么默认始节点为虚拟的源点 if(s == INVALID) s = vnet->vSource(); //如果末节点的值"无效"(INVALID),那么默认末节点为虚拟的汇点 if(t == INVALID) t = vnet->vTarget(); //如果k小于等于0,则默认k=1(也就是搜索第1最大阻力路线) if(k<=0) k = 1; //以分支阻力为权重 Weight w(vnet->graph(), 0); GraphUtils::BuildWeight(vnet->graph(), w, PressureWeightFunc(vnet)); //权重取负值,将求最大权重相关的问题(例如最长路径,最大阻力路线等)转换成最短路径问题 GraphUtils::ReverseWeight(vnet->graph(), w); //用FilterArc适配器过滤一部分分支 typedef FilterArcs<Digraph, ArcFilter> Adaptor; Adaptor adaptor(vnet->graph(), arc_filter); //计算节点到末节点t的最短路径 DistMap dist(vnet->graph(), DBL_MAX); GraphUtils::BackSPFA(adaptor, w, t, dist); //节点的前驱节点(父节点),用于后续计算路径 PredMap pred(vnet->graph(), INVALID); //使用A*算法搜索k最短路径 if(!A_star(adaptor, w, s, t, k, dist, pred)) return false; //根据前向节点查找路径 bool ret = PathFromPred(vnet, s, t, pred, p); return (ret && !p.empty()); }
bool IdentifyLiaisonTunnel::findInOutEdges( Digraph::Arc le, EdgeArray& es1, EdgeArray& es2 ) { if( le == INVALID ) return false; for( Digraph::InArcIt e( dg, dg.source( le ) ); e != INVALID; ++e ) { if( datas[e]->et == ET_VIRTUAL ) continue; // 排除处理掘进工作面时增加的虚拟分支 es1.append( e ); } for( Digraph::OutArcIt e( dg, dg.target( le ) ); e != INVALID; ++e ) { if( datas[e]->et == ET_VIRTUAL ) continue; // 排除处理掘进工作面时增加的虚拟分支 es2.append( e ); } return true; }
static int Simple_AdjustFunc( Digraph& dg, VNO_EdgeMap& ed, VNO_FanMap& fd, const EdgeArray& maxPath, const EdgeArray& adjustPath, const EdgeArray& adjustEdges, double maxH, double adjustH) { //任选一条分支处理(实验玩玩) if(adjustEdges.empty()) { return -1; } else { srand(time(0)); return (rand()%adjustEdges.size()); } //return -1; }
static bool CriticalPathMethod(DGR& dg, Weight& w, Digraph::Node s, Digraph::Node t, EdgeArray& p) { //搜索关键活动分支 EdgeArray criticalEdges; CriticalActivity(dg, w, criticalEdges); if(criticalEdges.empty()) return false; //过滤非关键活动分支,dfs搜索关键路径 //基本原理:过滤掉其它非关键活动分支,执行一次dfs typename DGR::template ArcMap<bool> arc_filter(dg, false); GraphUtils::BuildArcFilter(criticalEdges, arc_filter, true); //用FilterArc适配器过滤一部分分支 typedef FilterArcs<DGR, ArcFilter> Adaptor; Adaptor adaptor(dg, arc_filter); return GraphUtils::DFS_Path(adaptor, s, t, p); }
// // Draws the edges of a silhouette, mostly just used for debugging pyrposes // but does give an informative view of what the silhouette looks like. // void Renderer::drawSilhouette(EdgeArray& sil) const { glPushAttrib(GL_LIGHTING_BIT); glDisable(GL_LIGHTING); // Loop through each edge in the silhouette array, get a Vertex for(EdgeArray::const_iterator edge = sil.begin(); edge != sil.end(); ++edge) { glBegin(GL_LINES); glColor3f(1.0, 0.0, 0.0); glVertex(edge->getVertex(0)); glColor3f(0.0, 1.0, 0.0); glVertex(edge->getVertex(1)); glEnd(); } glPopAttrib(); }
Iterator& operator++() { if ((m_i0 >= 0) && (m_p < m_edgeArray->size() - 1)) { ++m_p; } else { // Skip over elements with no face array do { ++m_i0; if (m_i0 == m_array.size()) { m_end = true; return *this; } else { m_edgeArray = &m_array[m_i0]; m_p = 0; } } while (m_edgeArray->size() == 0); } return *this; }
static void PrintMRP(Digraph& dg, EdgeIdMap& eid, NodeIdMap& nid, VNO_EdgeMap& ed, VNO_FanMap&fd, EdgeArray& p) { cout<<"最大阻力路线:"<<endl; for(size_t i=0;i<p.size();i++) { Digraph::Arc e = p[i]; int id = eid[e]; cout<<"e"<<id<<"->"; } cout<<endl; }
bool IdentifyLiaisonTunnel::doILT4( EdgeArray& edges ) { if( !isInitNetworkOk() ) return false; if( airEdges.isEmpty() ) return false; NodeFilter nf( dg, true ); BuildNodeFilter( dg, airEdges, sn, tn, nf ); IntMap imap( dg ); Init_IMap( dg, ef, nf, airEdges, imap ); // 记录节点的入度和出度 // 过滤阻断分支 IntMap inDeg( dg ), outDeg( dg ); InitDegMap( dg, ef, inDeg, outDeg ); bool bQuit = false; while( !bQuit ) { bQuit = true; for( Digraph::ArcIt e( dg ); e != INVALID; ++e ) { if( !ef[e] || datas[e]->et == ET_VIRTUAL ) continue; Digraph::Node u = dg.source( e ); Digraph::Node v = dg.target( e ); if( imap[u]*imap[v] <= 0 ) continue; if( outDeg[u] - 1 <= 0 || inDeg[v] - 1 <= 0 ) continue; if( imap[v] < 0 ) { bool ret = false; // 回风区,考察节点的入边是否有新风流入 for( Digraph::InArcIt ie( dg, v ); ie != INVALID; ++ie ) { if( imap[dg.source( ie )] > 0 ) { ret = true; break; } } if( ret ) continue; } outDeg[u] = outDeg[u] - 1; inDeg[v] = inDeg[v] - 1; edges.append( e ); bQuit = false; } } return true; }
void buildEdgeArray( int n, EdgeArray &e, Matrix &m ) { int right_m_bound = 1; for( int i = 1; i < n; i++ ) { for( int j = 0; j < right_m_bound; j++ ) { if( i != j && m.get( i, j ) != INF ) e.append( i, j, m.get( i, j ) ); } ++right_m_bound; } }
static void DisplayAirEdgeNum( EdgeArray& airEdges, ILT_EdgeDataMap2& datas ) { AcDbObjectIdArray objIds2; AcDbIntArray ivs3; int len = airEdges.length(); for( int i = 0; i < len; i++ ) { Digraph::Arc e = airEdges[i]; objIds2.append( datas[e]->objId ); ivs3.append( i ); } DisplayIntValue( objIds2, ivs3 ); }
static void FindStationFromNode( Digraph& dg, Digraph::Node u, EdgeArray& es, bool reverse = false ) { NDArray nds; if( reverse ) { DFS_Helper3( dg, u, nds ); } else { DFS_Helper2( dg, u, nds ); } std::sort( nds.begin(), nds.end(), SortNodeDist() ); for( int i = 0; i < nds.size(); i++ ) { if( i < MAX_PATH_LENGTH ) { bool ret = true; DPath p; if( reverse ) { ret = DFS_Helper( dg, nds[i].u, u, p ); } else { ret = DFS_Helper( dg, u, nds[i].u, p ); } if( !ret ) continue; for( DPath::ArcIt e( p ); e != INVALID; ++e ) { if( !es.contains( e ) ) es.append( e ); } } } }
static Digraph::Arc FindStationEdge( FWS_EdgeDataMap& datas, EdgeArray& es ) { Digraph::Arc wsEdge = INVALID; int len = es.length(); for( int i = 0; i < len; i++ ) { Digraph::Arc e = es[i]; if( datas[e]->et != ET_VIRTUAL && HasStation( datas[e]->objId ) ) { wsEdge = e; break; } } return wsEdge; }
static void FindILTEdges( Digraph& dg, ILT_EdgeDataMap2& datas, IntMap& cmap, EdgeArray& edges ) { for( Digraph::ArcIt e( dg ); e != INVALID; ++e ) { if( datas[e]->et == ET_VIRTUAL ) continue; Digraph::Node u = dg.source( e ); Digraph::Node v = dg.target( e ); // 排除直接相连的分支 // 联络巷分支的始节点出度必须大于1,末节点的入度必须大于1 if( countOutArcs( dg, u ) <= 1 || countInArcs( dg, v ) <= 1 ) continue; if( cmap[u]*cmap[v] < 0 ) edges.append( e ); } }
void CPlanarSubClusteredST::call(const ClusterGraph &CG, EdgeArray<bool>& inST) { initialize(CG); inST.fill(false); //representationsgraphs for every cluster, on clustergraph ClusterArray<Graph*> l_clusterRepGraph(CG, nullptr); computeRepresentationGraphs(CG, l_clusterRepGraph); //now we compute the spanning trees on the representation graphs //we should save the selection info on the original edge //are statically on the repgraphedges (we only have edge -> repedge //information) but ClusterArray< EdgeArray<bool> > l_inTree(CG); for(cluster c : CG.clusters) { l_inTree[c].init(*l_clusterRepGraph[c], false); //compute STs NodeArray<bool> visited(*l_clusterRepGraph[c], false); dfsBuildSpanningTree(l_clusterRepGraph[c]->firstNode(), l_inTree[c], visited); } OGDF_ASSERT(isConnected(CG.constGraph())); //compute the subclustered graph by constructing a spanning tree //using only the representation edges used in STs on the repgraphs NodeArray<bool> visited(CG, false); dfsBuildOriginalST(CG.constGraph().firstNode(), l_inTree, inST, visited); //unregister the edgearrays to avoid destructor failure after //representation graph deletion for(cluster c : CG.clusters) { l_inTree[c].init(); } deleteRepresentationGraphs(CG, l_clusterRepGraph); }
bool mrp_cpm(VentNetwork* vnet, ArcFilter& arc_filter, Digraph::Node s, Digraph::Node t, EdgeArray& p) { //如果始节点的值"无效"(INVALID),那么默认始节点为虚拟的源点 if(s == INVALID) s = vnet->vSource(); //如果末节点的值"无效"(INVALID),那么默认末节点为虚拟的汇点 if(t == INVALID) t = vnet->vTarget(); //以分支阻力为权重 Weight w(vnet->graph()); GraphUtils::BuildWeight(vnet->graph(), w, PressureWeightFunc(vnet)); //用FilterArc适配器过滤一部分分支 typedef FilterArcs<Digraph, ArcFilter> Adaptor; Adaptor adaptor(vnet->graph(), arc_filter); //搜索关键路径(也即最大阻力路线) EdgeArray pp; if(!CriticalPathMethod(adaptor, w, s, t, pp)) return false; //过滤虚拟分支 vnet->filterVirutalEdges(pp, p); return (!p.empty()); }
bool mrp_k(Digraph& dg, ArcFilter& arc_filter, Digraph::Node s, Digraph::Node t, int k, EdgeArray& p) { //以分支阻力为权重 Weight w(dg, -1); //用FilterArc适配器过滤一部分分支 typedef FilterArcs<Digraph, ArcFilter> Adaptor; Adaptor adaptor(dg, arc_filter); //计算节点到末节点t的最短路径 DistMap dist(dg, DBL_MAX); GraphUtils::BackSPFA(adaptor, w, t, dist); //节点的前驱节点(父节点),用于后续计算路径 PredMap pred(dg, INVALID); //使用A*算法搜索k最短路径 if(!A_star(adaptor, w, s, t, k, dist, pred)) return false; //acutPrintf(_T("\n根据前向节点查找路径")); //根据前向节点查找路径 bool ret = PathFromPred(dg, s, t, pred, p); return (ret && !p.empty()); }
static void DisplayEdgeCMapValue( Digraph& dg, EdgeArray& sortedAirEdges, ILT_EdgeDataMap2& datas, IntMap& cmap, AcDbIntArray& sAirs, AcDbIntArray& tAirs ) { AcDbObjectIdArray objIds; AcDbIntArray ivs, ivs2; for( Digraph::ArcIt e( dg ); e != INVALID; ++e ) { objIds.append( datas[e]->objId ); int pos = sortedAirEdges.find( e ); if( pos != -1 ) { ivs.append( sAirs[pos] ); ivs2.append( tAirs[pos] ); } else { ivs.append( cmap[dg.source( e )] ); ivs2.append( cmap[dg.target( e )] ); } } DisplayIntValue2( objIds, ivs, ivs2 ); }
static void Init_IMap( Digraph& dg, ArcFilter& ef, NodeFilter& nf, EdgeArray& airEdges, IntMap& imap ) { AFGraph afg( dg, ef ); for( Digraph::NodeIt n( dg ); n != INVALID; ++n ) { imap[n] = ( nf[n] ? 1 : 0 ); // 默认所有节点位于进风区 } int len = airEdges.length(); for( int i = 0; i < len; i++ ) { Digraph::Arc e = airEdges[i]; Digraph::Node u = dg.source( e ); Digraph::Node v = dg.target( e ); Dfs<AFGraph> bDfs( afg ); bDfs.run( v ); for( Digraph::NodeIt n( dg ); n != INVALID; ++n ) { if( nf[n] && bDfs.reached( n ) ) imap[n] = -1; // 节点位于回风区 } } }
// 标记用风地点的始末节点和网络源汇节点 // 在搜索的时候,不搜索这些节点 static void BuildNodeFilter( Digraph& dg, EdgeArray& airEdges, Digraph::Node s, Digraph::Node t, NodeFilter& nf ) { int len = airEdges.length(); acutPrintf( _T( "\n用风地点个数:%d" ), len ); for( int i = 0; i < len; i++ ) { Digraph::Arc e = airEdges[i]; nf[dg.source( e )] = false; nf[dg.target( e )] = false; } nf[s] = false; nf[t] = false; // 原始网络的源点和汇点也要标记 for( Digraph::OutArcIt e( dg, s ); e != INVALID; ++e ) { nf[dg.target( e )] = false; } for( Digraph::InArcIt e( dg, t ); e != INVALID; ++e ) { nf[dg.source( e )] = false; } }
//指定一些特殊分支,要求搜索一条路径时尽可能多的通过这些特殊分支 //例如:搜索一条串联通风路径(通过多个用风地点的一条路径) //采用二分匹配实现失败!!! static bool MaxKeyEdgePass_Match(Digraph& dg, EdgeArray& airEdges, Digraph::Node s, Digraph::Node t, EdgeArray& mpp) { EdgeArray p; if(!GraphUtils::DFS_Path(dg, s, t, p)) return false; typedef Digraph::NodeMap<Digraph::Node> DDMap; DDMap ddm(dg, INVALID); NodeArray left, right; left.push_back(s); right.push_back(t); for(size_t i=0;i<airEdges.size();i++) { Digraph::Arc e = airEdges[i]; Digraph::Node u = dg.source(e); Digraph::Node v = dg.target(e); p.clear(); bool ret = GraphUtils::DFS_Path(dg, v, t, p); if(!ret) continue; p.clear(); ret = GraphUtils::DFS_Path(dg, s, u, p); if(!ret) continue; left.push_back(v); right.push_back(u); } //cout<<"left="<<left.size()<<" right="<<right.size()<<endl; ListGraph g; ListGraph::NodeMap<Digraph::Node> udm(g); typedef std::vector<ListGraph::Node> UNodeArray; UNodeArray left_nodes, right_nodes; typedef std::map<Digraph::Node, ListGraph::Node> DUMap; DUMap dum; //添加节点 for(size_t i=0;i<left.size();i++) { Digraph::Node u = left[i]; ListGraph::Node uu = g.addNode(); udm[uu] = u; left_nodes.push_back(uu); //cout<<dg.id(u)<< " "; } //cout<<endl; for(size_t i=0;i<right.size();i++) { Digraph::Node u = right[i]; ListGraph::Node uu = g.addNode(); udm[uu] = u; right_nodes.push_back(uu); //cout<<dg.id(u)<<" "; } //cout<<endl; for(size_t i=0;i<right.size();i++) { Digraph::Node u = right[i]; ListGraph::Node uu = g.addNode(); udm[uu] = u; left_nodes.push_back(uu); //cout<<dg.id(u)<< " "; } //cout<<endl; for(size_t i=0;i<left.size();i++) { Digraph::Node u = left[i]; ListGraph::Node uu = g.addNode(); udm[uu] = u; right_nodes.push_back(uu); //cout<<dg.id(u)<< " "; } //cout<<endl; //添加分支 for(size_t i=0;i<left_nodes.size();i++) { ListGraph::Node uv = left_nodes[i]; for(size_t j=0;j<right_nodes.size();j++) { ListGraph::Node uu = right_nodes[j]; Digraph::Node v = udm[uv]; Digraph::Node u = udm[uu]; if(u == v) continue; p.clear(); if(GraphUtils::DFS_Path(dg, v, u, p)) { //ListGraph::Node uv = left_nodes[i]; //ListGraph::Node uu = right_nodes[j]; ListGraph::Edge e = g.addEdge(uu,uv); //cout<<"二分图:"<<dg.id(v)<<"<-->"<<dg.id(u)<<endl; } } } //二分图最大匹配 MaxMatching<ListGraph> mm(g); mm.run(); //cout<<"分支数:"<<countEdges(g)<<" 匹配数:"<<mm.matchingSize()<<endl; for(ListGraph::EdgeIt e(g);e!=INVALID;++e) { if(mm.matching(e)) { ListGraph::Node du = g.u(e); ListGraph::Node dv = g.v(e); Digraph::Node u = udm[du]; Digraph::Node v = udm[dv]; //cout<<"匹配:"<<dg.id(v)<<"<-->"<<dg.id(u)<<endl; if(ddm[u] != INVALID && ddm[v] == INVALID) { ddm[v] = u; //cout<<" v"<<dg.id(v)<<"-->v"<<dg.id(u) <<" v"<<dg.id(u)<<"-->"<<dg.id(ddm[u])<<endl; } else if(ddm[v] != INVALID && ddm[u] == INVALID) { ddm[u] = v; //cout<<" v"<<dg.id(v)<<"-->v"<<dg.id(ddm[v]) <<" v"<<dg.id(u)<<"-->"<<dg.id(v)<<endl; } } } NodeArray node_path; Digraph::Node u = s; bool ret = true; while(u != t) { Digraph::Node v = ddm[u]; //cout<<dg.id(u)<<"->"<<endl; if(v == INVALID) { //cout<<"错误"<<endl; ret = false; break; } //cout<<" ->"<<dg.id(v)<<" "<<endl; node_path.push_back(v); u = v; } if(ret) { u = s; for(size_t i=0;i<node_path.size();i++) { Digraph::Node v = node_path[i]; GraphUtils::DFS_Path(dg, u, v, mpp); u = v; } } return ret; }
//指定一些特殊分支,要求搜索一条路径时尽可能多的通过这些特殊分支 //例如:搜索一条串联通风路径(通过多个用风地点的一条路径) //使用关键路径算法实现 static bool MaxKeyEdgePass_CPM(Digraph& dg, EdgeArray& airEdges, Digraph::Node s, Digraph::Node t, EdgeArray& mpp) { EdgeArray p; if(!GraphUtils::DFS_Path(dg, s, t, p)) return false; NodeArray left, right; left.push_back(s); right.push_back(t); for(size_t i=0;i<airEdges.size();i++) { Digraph::Arc e = airEdges[i]; Digraph::Node u = dg.source(e); Digraph::Node v = dg.target(e); p.clear(); bool ret = GraphUtils::DFS_Path(dg, v, t, p); if(!ret) continue; p.clear(); ret = GraphUtils::DFS_Path(dg, s, u, p); if(!ret) continue; left.push_back(v); right.push_back(u); } //cout<<"left="<<left.size()<<" right="<<right.size()<<endl; //构造新的图 Digraph new_dg; //记录新图节点和原始图节点的关系 Digraph::NodeMap<Digraph::Node> udm(new_dg); //记录原始图节点与新构造图节点的关系 typedef std::map<Digraph::Node, Digraph::Node> DDMap; DDMap ddm; //左右节点数组 NodeArray left_nodes, right_nodes; //添加节点 for(size_t i=0;i<left.size();i++) { Digraph::Node u = left[i], uu = INVALID; DDMap::iterator itr = ddm.find(u); if(itr == ddm.end()) { uu = new_dg.addNode(); } else { uu = itr->second; } udm[uu] = u; ddm[u] = uu; left_nodes.push_back(uu); //cout<<dg.id(u)<< " "; } //cout<<endl; for(size_t i=0;i<right.size();i++) { Digraph::Node u = right[i], uu = INVALID; DDMap::iterator itr = ddm.find(u); if(itr == ddm.end()) { uu = new_dg.addNode(); } else { uu = itr->second; } udm[uu] = u; ddm[u] = uu; right_nodes.push_back(uu); //cout<<dg.id(u)<<" "; } //cout<<endl; //添加分支 for(size_t i=0;i<left_nodes.size();i++) { Digraph::Node uv = left_nodes[i]; for(size_t j=0;j<right_nodes.size();j++) { Digraph::Node uu = right_nodes[j]; Digraph::Node v = udm[uv]; Digraph::Node u = udm[uu]; if(u == v || (v == s && u == t)) continue; p.clear(); if(GraphUtils::DFS_Path(dg, v, u, p)) { Digraph::Arc e = new_dg.addArc(uv,uu); //cout<<"新图:"<<dg.id(v)<<"<-->"<<dg.id(u)<<endl; } } } for(size_t i=0;i<left_nodes.size();i++) { Digraph::Node uv = left_nodes[i]; Digraph::Node uu = right_nodes[i]; Digraph::Node v = udm[uv]; Digraph::Node u = udm[uu]; if(u == v || u == t) continue; Digraph::Arc e = new_dg.addArc(uu,uv); //cout<<"新图:"<<dg.id(u)<<"<-->"<<dg.id(v)<<endl; } //新图搜索关键路径,分配权重,默认为1(最长路径) Weight w(new_dg); GraphUtils::BuildWeight(new_dg, w, DefWeightFunc()); EdgeArray pp; if(!CriticalPathMethod(new_dg, w, left_nodes[0], right_nodes[0], pp)) return false; //cout<<"搜索关键路径:"<<pp.size()<<endl; bool ret = true; //转换成实际图的分支 for(size_t i=0;i<pp.size();i++) { Digraph::Arc ee = pp[i]; Digraph::Node uu = new_dg.source(ee); Digraph::Node uv = new_dg.target(ee); Digraph::Node u = udm[uu]; Digraph::Node v = udm[uv]; EdgeArray ppp; if(!GraphUtils::DFS_Path(dg, u, v, ppp)) { ret = false; mpp.clear(); break; } else { std::copy(ppp .begin(), ppp .end(), std::back_inserter(mpp)); } } //cout<<"mpp:"<<mpp.size()<<endl; return ret; }