Here’s a helpful, explanatory text for understanding and implementing the Tideman problem from CS50 (the “locked pairs” voting method). It’s not the full code, but a reasoning guide to help you write your own solution.
bool vote(int rank, char *name, int ranks[])
void record_preferences(int ranks[])
void add_pairs(void)
void sort_pairs(void)
bool creates_cycle(int winner, int loser)
void lock_pairs(void)
void print_winner(void)
Before touching code, you must understand the three core stages:
The winner is the candidate who ends up at the “source” of the locked graph (no incoming edges). Cs50 Tideman Solution
The distribution code provides a skeleton with these functions:
vote(int rank, string name, int ranks[]): Records a voter’s preference order.record_preferences(int ranks[]): Updates the global preferences[i][j] matrix (how many voters prefer i over j).add_pairs(void): Adds all pairs where one candidate beats another to the pairs array.sort_pairs(void): Sorts the pairs by decreasing margin of victory.lock_pairs(void): Locks pairs in order, avoiding cycles.print_winner(void): Prints the candidate with no incoming edges in the locked graph.The main challenge is lock_pairs. Many students implement everything else correctly but fail cycle detection.
This paper explores the algorithmic logic and implementation required to solve the "Tideman" problem from Harvard University’s CS50: Introduction to Computer Science course. The Tideman voting method (also known as Ranked Pairs) is a Condorcet method used to determine election results where voters rank candidates. This paper details the data structures used to represent the voting graph, the critical process of "locking" pairs to prevent cycles, and the specific programming strategies used to implement the sort_pairs, lock_pairs, and print_winner functions. Here’s a helpful, explanatory text for understanding and
tideman.c#include <stdio.h>
#include <stdlib.h>
// Structure to represent a candidate
typedef struct candidate
int id;
int votes;
candidate_t;
// Structure to represent a voter
typedef struct voter
int *preferences;
voter_t;
// Function to read input
void read_input(int *voters, int *candidates, voter_t **voters_prefs)
// Read in the number of voters and candidates
scanf("%d %d", voters, candidates);
// Allocate memory for voters and candidates
*voters_prefs = malloc(*voters * sizeof(voter_t));
candidate_t *candidates_list = malloc(*candidates * sizeof(candidate_t));
// Read in voter preferences
for (int i = 0; i < *voters; i++)
(*voters_prefs)[i].preferences = malloc(*candidates * sizeof(int));
for (int j = 0; j < *candidates; j++)
scanf("%d", &(*voters_prefs)[i].preferences[j]);
// Function to count first-place votes
void count_first_place_votes(voter_t *voters_prefs, int voters, candidate_t *candidates_list, int candidates)
// Initialize vote counts to 0
for (int i = 0; i < candidates; i++)
candidates_list[i].votes = 0;
// Count first-place votes
for (int i = 0; i < voters; i++)
for (int j = 0; j < candidates; j++)
if (j == 0)
candidates_list[voters_prefs[i].preferences[j] - 1].votes++;
// Function to check for winner
int check_for_winner(candidate_t *candidates_list, int candidates)
// Check if any candidate has more than half of the first-place votes
for (int i = 0; i < candidates; i++)
if (candidates_list[i].votes > candidates / 2)
return i + 1;
return -1;
// Function to eliminate candidate
void eliminate_candidate(candidate_t *candidates_list, int candidates, int eliminated)
// Decrement vote counts for eliminated candidate
for (int i = 0; i < candidates; i++)
if (candidates_list[i].id == eliminated)
candidates_list[i].votes = 0;
// Function to recount votes
void recount_votes(voter_t *voters_prefs, int voters, candidate_t *candidates_list, int candidates)
// Recount votes
for (int i = 0; i < voters; i++)
for (int j = 0; j < candidates; j++)
if (candidates_list[voters_prefs[i].preferences[j] - 1].votes == 0)
// Move to next preference
voters_prefs[i].preferences[j] = -1;
else
break;
int main()
int voters, candidates;
voter_t *voters_prefs;
read_input(&voters, &candidates, &voters_prefs);
candidate_t *candidates_list = malloc(candidates * sizeof(candidate_t));
for (int i = 0; i < candidates; i++)
candidates_list[i].id = i + 1;
count_first_place_votes(voters_prefs, voters, candidates_list, candidates);
int winner = check_for_winner(candidates_list, candidates);
while (winner == -1)
// Eliminate candidate with fewest votes
int eliminated = -1;
int min_votes = voters + 1;
for (int i = 0; i < candidates; i++)
if (candidates_list[i].votes < min_votes)
min_votes = candidates_list[i].votes;
eliminated = candidates_list[i].id;
eliminate_candidate(candidates_list, candidates, eliminated);
recount_votes(voters_prefs, voters, candidates_list, candidates);
count_first_place_votes(voters_prefs, voters, candidates_list, candidates);
winner = check_for_winner(candidates_list, candidates);
printf("The winner is: %d\n", winner);
return 0;