A C++ CLI tool that matches candidates to companies with fixed seat counts using a Gale–Shapley-style stable matching algorithm — built for the PM Internship Scheme allocation problem (SIH25033/34).
Match N candidates to M companies, each with a fixed number of seats, such that the final assignment is stable: no candidate-company pair exists where both would rather switch away from their current match to be with each other.
- Score — every candidate is scored against every company using skill overlap, CGPA, and sector/location preference alignment.
- Rank — each candidate's scores are sorted into a preference list (most-preferred company first).
- Allocate — candidates are processed one at a time from a queue:
- If their top remaining choice has an open seat, they're placed.
- If the seat is full, they're compared against the weakest candidate currently holding a seat there. Higher score → they take the seat and displace the weaker candidate (who re-enters the queue). Lower score → they move on to their next preference.
- Terminate — the loop ends when every candidate is placed or has exhausted their preference list.
This guarantees the result is stable — the same mathematical guarantee Gale-Shapley provides.
| Structure | Where | Purpose |
|---|---|---|
Hash Map (unordered_map) |
candidates_, companies_, scoreCache_ |
O(1) lookup by ID; caches every pairwise score so it's never recomputed |
Min-Heap (priority_queue, size = seat count) |
Company::heldSeats |
Top of heap = weakest currently-held candidate → O(1) peek, O(log seats) displacement instead of scanning all seat-holders |
Queue (std::queue) |
pool in Allocator::runAllocation |
Drives the main loop: holds not-yet-placed candidates, re-enqueues anyone displaced |
Sorting (std::sort) |
Allocator::buildPreferenceLists |
Run once per candidate to turn raw scores into a ranked preference list |
pm_allocation_engine/
├── include/ Header files (candidate.h, company.h, scoring.h, csv_utils.h, allocator.h)
├── src/ Implementation files + main.cpp (CLI menu)
├── data/ candidates.csv, companies.csv (sample/input data)
├── Makefile
└── README.md
make clean && make
./allocator_appMenu flow (must be done in order):
- Load candidates & companies from CSV — press Enter twice to accept
the default paths (
data/candidates.csv,data/companies.csv) - Build preference lists — scores + sorts every candidate
- Run stable allocation — runs the queue/heap matching process
- View results — prints final matches per company + any unmatched candidates
- Export results to CSV — saves to
results.csv - Exit
candidates.csv
id,name,skills(;-separated),cgpa,sector,location
companies.csv
id,name,required_skills(;-separated),seats,sector,location
Each candidate-company score (0–100) is a weighted sum of:
- Skill overlap — 50%
- CGPA (normalized out of 10) — 30%
- Sector match — 10%
- Location match — 10%
Weights are adjustable in src/scoring.cpp.
- Change scoring weights or logic in
scoring.cpp. - Add a hard skill-requirement filter before building preference lists if partial matches shouldn't be considered at all.
- The
Allocatorclass is decoupled from CLI I/O, so a future UI (web or desktop) can reuse it directly without changes to the core algorithm.
CLI version — functional and tested. UI layer planned as a later phase.