/* 
 * File:   graph.cpp
 * Author: Muhammad Faruq Nuruddinsyah
 *
 * Created on May 2, 2013, 9:26 AM
 */

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Node;
class Edge;
class Graph;

class Node{
public:
    string name;
    vector<Edge*> edges;
    
    Node(string nama){
        name = nama;
    }
    
    void add_adjacent(Node* a, int cost, bool two_way);
};

class Edge{
public:
    int cost;
    Node* adjacent;
    
    Edge(Node* a, int c){
        cost = c;
        adjacent = a;
    }
};

void Node::add_adjacent(Node* a, int cost, bool two_way = false){
    edges.push_back(new Edge(a, cost));
    
    if(two_way){
        a->edges.push_back(new Edge(this, cost));
    }
}

class Graph{
public:
    vector<Node*> nodes;
    
    void add_node(string name){
        nodes.push_back(new Node(name));
    }
    
    void connect(string node1, string node2, int cost, bool two_way = false){
        Node* n1 = get_node(node1);
        Node* n2 = get_node(node2);
        
        if(n1 == NULL || n2 == NULL) return;
        
        n1->add_adjacent(n2, cost, two_way);
    }
    
    void print(){
        for(int i = 0; i < nodes.size(); i++){
            cout << nodes.at(i)->name << ": ";
            
            for(int j = 0; j < nodes.at(i)->edges.size(); j++){
                cout << nodes.at(i)->edges.at(j)->adjacent->name << " ";
            }
            
            cout << endl;
        }
    }

private:
    Node* get_node(string name){
        for(int i = 0; i < nodes.size(); i++){
            if(nodes.at(i)->name.compare(name) == 0){
                return nodes.at(i);
            }
        }
        
        return NULL;
    }
};

int main(){
    Graph* g = new Graph();
    
    g->add_node("A");
    g->add_node("B");
    g->add_node("C");
    g->add_node("D");
    
    g->connect("A", "B", 2, true);
    g->connect("A", "C", 10, true);
    g->connect("C", "D", 7, true);
    
    g->print();
}