There has to be a more elegant way to do this, but this was my solution:
I did this using two main processes: an outer process that picks nodes to test, and an inner process that broadcasts the message and counts relays. In both of the processes I maintain lists of nodes that have already been tested or relayed, so that I don’t end up re-testing/re-counting nodes.
For the outer process:
I started with the node with the highest number of neighbors as the first node.
Run the inner process (see below), and store the number of relays as the starting "minimum relays"
1. Run the inner process for each of the neighbors of that node, keeping track of the number of relays for each.
2. If any of those nodes are lower than the current minimum relays, the lowest of those becomes the source node for the next set of nodes to test.
3. Repeat until all viable nodes have been tested
By doing this, you’re targeting each test at a better node, narrowing down the list each time.
For the inner process:
* I created two loops: one that loops through a “current nodes” list, and one that adds nodes to a “next nodes” list, based on each of the “current nodes.”
* For each iteration through the complete “current nodes” list, I increment a relay counter.
* If at any time the relay counter becomes greater than the current “minimum relays”, I break out of the process.
* At the end of the loop, the "next nodes" list becomes the "current nodes" list.
* Repeat until all nodes have been relayed.