USACO 1.1 Greedy Gift Givers

The algorithm is simple but it is a pain in the ass to parse input and extract names.

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <unordered_map>

using namespace std;

struct Person {
int size;
vector<Person*> toList;
int money;
int left;
int sum;
string name;

Person(string name) : size(0), money(0), left(0), name(name) {}
};

int main() {
ofstream fout ("gift1.out");
ifstream fin ("gift1.in");

string input;
getline(fin, input);
int total = stoi(input);

// Each line contains the name of a group member
unordered_map<string, Person*> hashmap;
vector<Person*> personList;
for (int i = 0; i < total; ++i) {
string name;
getline(fin, name);
auto person = new Person(name);
hashmap[name] = person;
personList.push_back(person);
}

/*
The first line in the group tells the person's name who will be giving gifts.
The second line in the group contains two numbers: The initial amount of money (in the range 0..2000) to be divided up into gifts by the giver and then the number of people to whom the giver will give gifts, NGi (0 ≤ NGi ≤ NP-1).
If NGi is nonzero, each of the next NGi lines lists the the name of a recipient of a gift.
*/
for (int i = 0; i < total; ++i) {
string name;
getline(fin, name);
auto person = hashmap[name];

fin >> person->money >> person->size;
string newline;
getline(fin, newline);

if (!person->size)
person->left = person->money;
else if (person->size == 1)
person->left = 0;
else
person->left = person->money % person->size;

person->sum = person->left;

if (person->size) {
for (int j = 0; j < person->size; ++j) {
string toName;
getline(fin, toName);
person->toList.push_back(hashmap[toName]);
}
}
}

for (auto &item : hashmap) {
if (!item.second->size) continue;
int money = (item.second->money - item.second->left) / item.second->size;
for (auto &toPerson : item.second->toList) {
toPerson->sum += money;
}
}

for (auto &person : personList) {
fout << person->name << " " << person->sum - person->money << endl;
}

return 0;
}