0

I am trying to find a way in Python to pair up nodes in an undirected graph such that the maximal amounts of nodes is reached, while no node appears more than once.

Example:

Input1: Graph with 3 nodes and edges [A, B], [A, C], [B, C]

Output1: should be 2 because there is no way to choose more than one edge such that no node is repeated.

Input2: Graph with 6 nodes and edges [A, B], [A, C], [A, D], [B, D], [B, E], [B, F], [C, D], [C, F], [E, F]

Output2: should be 6 because all nodes can be paired. For example, with edges [A, B], [C, D], [E, F].

Andrew.M
  • 90
  • 1
  • 7
  • I started working on a solution, which basically makes a new graph, with edges being the nodes, and they are connected to the other edges which do not share nodes. And my idea is to find the longest path possible in the graph, but I don't know how to do that. – Andrew.M Jul 03 '22 at 13:11
  • i dont know if this will work. seems kind of greedy. but first make a tree. root node will be the one that has the most connections. so tree will look like [A->[B->[D E->[F] F] [C->[D F]] [D]]. then select the leaf edges starting with the lowest depth. so [E-F] remove all connections to E or F from the tree and repeat. [A->[B->[D] C->[D] D] ] and so on, selecting [B D], tree becomes [A->[C D]] then selcting [A C] and done – Ritwick Jha Jul 03 '22 at 13:59
  • "for n1, n2 in edges:" I am not very familiar with python - what does this do? I doubt it loops over the edges, ( N1N2 in my psuedocode is a single variable indexing the edge between nodes N1 and N2. ) – ravenspoint Jul 03 '22 at 15:53
  • It loops over the edges, but defines the first edge vertex as n1 and the second as n2. – Andrew.M Jul 03 '22 at 15:57
  • Python is a truly weird language. – ravenspoint Jul 03 '22 at 16:03
  • Yes, sorry, I actually just wrote the solution. It was heavily inspired by your pseudocode, so I will mark it as the answer. I also had a problem with duplicates and ended up saving the numbers with their indexes to add uniqueness. – Andrew.M Jul 03 '22 at 19:25

1 Answers1

1
LOOP N1N2 over edges
    C = Count of unique nodes connected to the two nodes connected by edge
    Store N1N2 in MM, a multimap keyed by C
LOOP N1N2 over MM, from smallest C
    Add N1N2 to RESULT
    Remove all edges connecting N1 or N2 from MM
OUTPUT RESULT

N1N2 is a single variable indexing the edge between nodes N1 and N2

Here is a C++ implementation of this algorithm

void cGraph::solve()
{
    myResult.clear();
    std::multimap <int, int > edgeMap;

    // loop over edges
    int i = -1;
    for (auto &n1n2 : vEdge)
    {
        i++;
        int c = countNeighbors(n1n2);

        // store edge index keyed by count of neigbors
        edgeMap.insert({ c, i });
    }

    // while edges remain unassigned
    while( edgeMap.size() )
    {
        // assign pair with fewest neigbors to result
        auto pair =  vEdge[ edgeMap.begin()->second ];
        myResult.push_back( pair );

        // remove edges that connect nodes in result
        bool done = false;
        while( ! done )
        {
            done = true;

            // loop over edges in map
            for(
            std::multimap <int, int >::iterator it = edgeMap.begin();
            it != edgeMap.end();
            it++ )
            {
                // check for edge connecting node just added to result
                auto e = vEdge[it->second];
                if( e.n1 == pair.n1 ||
                 e.n2 == pair.n1 ||
                 e.n1 == pair.n2 ||
                 e.n2 == pair.n2 ) {

                    // remove the edge, to prevent duplicate nodes in result
                    edgeMap.erase( it );

                    // continue search for edges that connect edges in result
                    done = false;
                    break;
                 }
            }
        }
    }

}

The output is

test 1
2 paired nodes found
1 2
test 2
6 paired nodes found
1 4
2 5
3 6

The complete code for the application is here https://gist.github.com/JamesBremner/266e273899df4ca2815762d4bc803474

ravenspoint
  • 19,093
  • 6
  • 57
  • 103