i am new to this site so i might not ask my question correctly which i am sorry for but i have been struggling with PSET 3 Tideman for quite a while. Currently i am on lock_
You may have misunderstood the logic required behind lock_pairs
, because your function is overly complicated. This is what you're asked to do-
Go through each pair one by one, and lock them if necessary
How to know, if it is necessary? Simple, you make sure locking them does not constitute a circle
What does "constitute a circle" mean? This is explained very well by the course itself. More info right there
But basically,
How would this work in the case of the votes above? Well, the biggest margin of victory for a pair is Alice beating Bob, since 7 voters prefer Alice over Bob (no other head-to-head matchup has a winner preferred by more than 7 voters). So the Alice-Bob arrow is locked into the graph first. The next biggest margin of victory is Charlie’s 6-3 victory over Alice, so that arrow is locked in next.
Next up is Bob’s 5-4 victory over Charlie. But notice: if we were to add an arrow from Bob to Charlie now, we would create a cycle! Since the graph can’t allow cycles, we should skip this edge, and not add it to the graph at all. If there were more arrows to consider, we would look to those next, but that was the last arrow, so the graph is complete.
This step-by-step process is shown below, with the final graph at right.
Now the real deal, how do you put this in code?
Like this-
// Recursive function to check if entry makes a circle
bool makes_circle(int cycle_start, int loser)
{
if (loser == cycle_start)
{
// If the current loser is the cycle start
// The entry makes a circle
return true;
}
for (int i = 0; i < candidate_count; i++)
{
if (locked[loser][i])
{
if (makes_circle(cycle_start, i))
{
// Forward progress through the circle
return true;
}
}
}
return false;
}
Essentially, to check if locking in a winner->loser makes a circle, you walk back the entries you have locked starting from the loser and going towards all the candidates this loser has won against. If you reach the winner somewhere along the way, that's a circle if I've ever seen one.
Note that circle_start
though, lest it gets confusing. That's only there to remember the original circle start (which is the winner
in the main loop in lock_pairs
). This is constant throughout the entire recursion. Remember, once again, our goal is to iterate through all the candidates loser
has won against (and also have been locked) and make sure none of these are circle_start
(aka the winner
that we are about to lock in).
So, that function right there does all the heavy lifting, your lock_pairs
function is gonna be extremely simple-
// Lock pairs into the candidate graph in order, without creating cycles
void lock_pairs()
{
for (int i = 0; i < pair_count; i++)
{
if (!makes_circle(pairs[i].winner, pairs[i].loser))
{
// Lock the pair unless it makes a circle
locked[pairs[i].winner][pairs[i].loser] = true;
}
}
}