deba@326: /* -*- mode: C++; indent-tabs-mode: nil; -*- deba@326: * deba@326: * This file is a part of LEMON, a generic C++ optimization library. deba@326: * deba@326: * Copyright (C) 2003-2008 deba@326: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport deba@326: * (Egervary Research Group on Combinatorial Optimization, EGRES). deba@326: * deba@326: * Permission to use, modify and distribute this software is granted deba@326: * provided that this copyright notice appears in all copies. For deba@326: * precise terms see the accompanying LICENSE file. deba@326: * deba@326: * This software is provided "AS IS" with no warranty of any kind, deba@326: * express or implied, and with no claim as to its suitability for any deba@326: * purpose. deba@326: * deba@326: */ deba@326: deba@326: #include deba@326: #include deba@326: #include deba@326: #include deba@326: #include deba@326: deba@326: #include "test_tools.h" deba@326: #include deba@326: #include deba@326: deba@326: using namespace std; deba@326: using namespace lemon; deba@326: deba@326: int main() { deba@326: deba@326: typedef ListGraph Graph; deba@326: deba@326: GRAPH_TYPEDEFS(Graph); deba@326: deba@326: Graph g; deba@326: g.clear(); deba@326: deba@326: std::vector nodes; deba@326: for (int i=0; i<13; ++i) deba@326: nodes.push_back(g.addNode()); deba@326: deba@326: g.addEdge(nodes[0], nodes[0]); deba@326: g.addEdge(nodes[6], nodes[10]); deba@326: g.addEdge(nodes[5], nodes[10]); deba@326: g.addEdge(nodes[4], nodes[10]); deba@326: g.addEdge(nodes[3], nodes[11]); deba@326: g.addEdge(nodes[1], nodes[6]); deba@326: g.addEdge(nodes[4], nodes[7]); deba@326: g.addEdge(nodes[1], nodes[8]); deba@326: g.addEdge(nodes[0], nodes[8]); deba@326: g.addEdge(nodes[3], nodes[12]); deba@326: g.addEdge(nodes[6], nodes[9]); deba@326: g.addEdge(nodes[9], nodes[11]); deba@326: g.addEdge(nodes[2], nodes[10]); deba@326: g.addEdge(nodes[10], nodes[8]); deba@326: g.addEdge(nodes[5], nodes[8]); deba@326: g.addEdge(nodes[6], nodes[3]); deba@326: g.addEdge(nodes[0], nodes[5]); deba@326: g.addEdge(nodes[6], nodes[12]); deba@326: deba@326: MaxMatching max_matching(g); deba@326: max_matching.init(); deba@326: max_matching.startDense(); deba@326: deba@326: int s=0; deba@326: Graph::NodeMap mate(g,INVALID); deba@326: max_matching.mateMap(mate); deba@326: for(NodeIt v(g); v!=INVALID; ++v) { deba@326: if ( mate[v]!=INVALID ) ++s; deba@326: } deba@326: int size=int(s/2); //size will be used as the size of a maxmatching deba@326: deba@326: for(NodeIt v(g); v!=INVALID; ++v) { deba@326: max_matching.mate(v); deba@326: } deba@326: deba@326: check ( size == max_matching.size(), "mate() returns a different size matching than max_matching.size()" ); deba@326: deba@326: Graph::NodeMap::DecompType> pos0(g); deba@326: max_matching.decomposition(pos0); deba@326: deba@326: max_matching.init(); deba@326: max_matching.startSparse(); deba@326: s=0; deba@326: max_matching.mateMap(mate); deba@326: for(NodeIt v(g); v!=INVALID; ++v) { deba@326: if ( mate[v]!=INVALID ) ++s; deba@326: } deba@326: check ( int(s/2) == size, "The size does not equal!" ); deba@326: deba@326: Graph::NodeMap::DecompType> pos1(g); deba@326: max_matching.decomposition(pos1); deba@326: deba@326: max_matching.run(); deba@326: s=0; deba@326: max_matching.mateMap(mate); deba@326: for(NodeIt v(g); v!=INVALID; ++v) { deba@326: if ( mate[v]!=INVALID ) ++s; deba@326: } deba@326: check ( int(s/2) == size, "The size does not equal!" ); deba@326: deba@326: Graph::NodeMap::DecompType> pos2(g); deba@326: max_matching.decomposition(pos2); deba@326: deba@326: max_matching.run(); deba@326: s=0; deba@326: max_matching.mateMap(mate); deba@326: for(NodeIt v(g); v!=INVALID; ++v) { deba@326: if ( mate[v]!=INVALID ) ++s; deba@326: } deba@326: check ( int(s/2) == size, "The size does not equal!" ); deba@326: deba@326: Graph::NodeMap::DecompType> pos(g); deba@326: max_matching.decomposition(pos); deba@326: deba@326: bool ismatching=true; deba@326: for(NodeIt v(g); v!=INVALID; ++v) { deba@326: if ( mate[v]!=INVALID ) { deba@326: Node u=mate[v]; deba@326: if (mate[u]!=v) ismatching=false; deba@326: } deba@326: } deba@326: check ( ismatching, "It is not a matching!" ); deba@326: deba@326: bool coincide=true; deba@326: for(NodeIt v(g); v!=INVALID; ++v) { deba@326: if ( pos0[v] != pos1[v] || pos1[v]!=pos2[v] || pos2[v]!=pos[v] ) { deba@326: coincide=false; deba@326: } deba@326: } deba@326: check ( coincide, "The decompositions do not coincide! " ); deba@326: deba@326: bool noarc=true; deba@326: for(EdgeIt e(g); e!=INVALID; ++e) { deba@326: if ( (pos[g.v(e)]==max_matching.C && deba@326: pos[g.u(e)]==max_matching.D) || deba@326: (pos[g.v(e)]==max_matching.D && deba@326: pos[g.u(e)]==max_matching.C) ) deba@326: noarc=false; deba@326: } deba@326: check ( noarc, "There are arcs between D and C!" ); deba@326: deba@326: bool oddcomp=true; deba@326: Graph::NodeMap todo(g,true); deba@326: int num_comp=0; deba@326: for(NodeIt v(g); v!=INVALID; ++v) { deba@326: if ( pos[v]==max_matching.D && todo[v] ) { deba@326: int comp_size=1; deba@326: ++num_comp; deba@326: std::queue Q; deba@326: Q.push(v); deba@326: todo.set(v,false); deba@326: while (!Q.empty()) { deba@326: Node w=Q.front(); deba@326: Q.pop(); deba@326: for(IncEdgeIt e(g,w); e!=INVALID; ++e) { deba@326: Node u=g.runningNode(e); deba@326: if ( pos[u]==max_matching.D && todo[u] ) { deba@326: ++comp_size; deba@326: Q.push(u); deba@326: todo.set(u,false); deba@326: } deba@326: } deba@326: } deba@326: if ( !(comp_size % 2) ) oddcomp=false; deba@326: } deba@326: } deba@326: check ( oddcomp, "A component of g[D] is not odd." ); deba@326: deba@326: int barrier=0; deba@326: for(NodeIt v(g); v!=INVALID; ++v) { deba@326: if ( pos[v]==max_matching.A ) ++barrier; deba@326: } deba@326: int expected_size=int( countNodes(g)-num_comp+barrier)/2; deba@326: check ( size==expected_size, "The size of the matching is wrong." ); deba@326: deba@326: return 0; deba@326: }