#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional> // reference_wrapper

using namespace std;

class Student;
class Prof;
class Subject;

class Dept
{
	string name;
	vector<reference_wrapper<Student>> students;
	vector<reference_wrapper<Prof>> profs;
public:
	Dept( string deptname ) : name(deptname) {}
	void addProf( Prof &p ) { profs.push_back(p); }
	void addStudent( Student &s ) { students.push_back(s); }
};

class Prof
{
	string name;
	Dept &dept;
	vector<reference_wrapper<Student>> students;
	vector<reference_wrapper<Subject>> subjects;
public:
	Prof( string name, Dept &dept ) : name(name), dept(dept) { dept.addProf(*this); }
	void addStudent( Student &s ) { students.push_back(s); }
	void addSubject( Subject &s ) { subjects.push_back(s); }
};

class Subject
{
	string name;
	Prof &prof;
	vector<reference_wrapper<Student>> students;
public:
	Subject( string name, Prof &p ) : name(name), prof(p) { p.addSubject(*this); }
	void addStudent( Student &s ) { students.push_back(s); }
};

class Student
{
	string name;
	Dept *dept;
	Prof *prof;
	vector<Subject *> subjects;
public:
	Student() : name(""), dept(0), prof(0) {}
	//Student(string name, Dept &dept, Prof &prof) : name(name), dept(dept), prof(prof) 
	//	{ dept.addStudent(*this); prof.addStudent(*this); }
	void set(string n, Dept *d, Prof *p) {name=n; dept=d; prof=p; 
					dept->addStudent(*this); prof->addStudent(*this); }
	void enroll( Subject *s ) { subjects.push_back(s); s->addStudent(*this); }
};

int main() 
{
	Dept *cep = new Dept("Computer Engineering");

	Prof *shinp = new Prof("Minho Shin", *cep );
	Prof *chop = new Prof("Sehyung Cho", *cep );

	Student *students = new Student[3];

	students[0].set("Chulsoo Kim", cep, shinp);
	students[1].set("Miyoung Choi", cep, chop);
	students[2].set("Kimoon Ahn", cep, shinp);

	vector<Subject *> *subjects =  new vector<Subject *>;

	subjects->push_back( new Subject("C++ Programming", *shinp) );
	subjects->push_back( new Subject("Java Programming", *shinp) );

	// vector<int> vi;
	// ...
	// vi[3];
	// vi.at(3);

	students[0].enroll( (*subjects)[0] );
	students[1].enroll( subjects->at(1) );
	students[2].enroll( (*subjects)[1] );

	// delete everything
	delete cep;
	delete shinp;
	delete chop;
	delete[] students;
	delete (*subjects)[0]; 
	delete (*subjects)[1]; 
	delete subjects;
}
