// -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; -*-
////////////////////////////////////////////////////////////////////
//
// $Id: max_dag.cpp 706 2010-06-22 14:58:23Z Sebastian Kupferschmid $
//
////////////////////////////////////////////////////////////////////

#include "max_dag.h"

#include <map>
#include <inttypes.h>
#include <cassert>
#include <iostream>

using namespace std;

namespace cg {

    void MaxDAG::get_result(vector<int>& result) {
	if(debug){
	    for(uint32_t i = 0; i < weighted_graph.size(); i++) {
		cout << "From " << i << ":";
		for(uint32_t j = 0; j < weighted_graph[i].size(); j++)
		    cout << " " << weighted_graph[i][j].first
			 << " [weight " << weighted_graph[i][j].second << "]";
		cout << endl;
	    }
	}
	vector<int> incoming_weights; // indexed by the graph's nodes
	incoming_weights.resize(weighted_graph.size(), 0);
	for(uint32_t node = 0; node < weighted_graph.size(); node++) {
	    const vector<pair<int, int> > &weighted_edges = weighted_graph[node];
	    for(uint32_t i = 0; i < weighted_edges.size(); i++)
		incoming_weights[weighted_edges[i].first] += weighted_edges[i].second;
	}
	
	// Build minHeap of nodes, compared by number of incoming edges.
	typedef multimap<int, int>::iterator HeapPosition;
	
	vector<HeapPosition> heap_positions;
	multimap<int, int> heap;
	for(uint32_t node = 0; node < weighted_graph.size(); node++) {
	    if(debug)
		cout << "node "<< node << " has "<< incoming_weights[node] << " edges" << endl;
	    HeapPosition pos = heap.insert(make_pair(incoming_weights[node], node));
	    heap_positions.push_back(pos);
	}
	vector<bool> done;
	done.resize(weighted_graph.size(), false);
	

	// Recursively delete node with minimal weight of incoming edges.
	while(!heap.empty()) {
	    if(debug) cout << "minimal element is " << heap.begin()->second << endl;
	    int removed = heap.begin()->second;
	    done[removed] = true;
	    result.push_back(removed);
	    heap.erase(heap.begin());
	    const vector<pair<int, int> > &succs = weighted_graph[removed];
	    for(uint32_t i = 0; i < succs.size(); i++) {
		int target = succs[i].first;
		if(!done[target]) {
		    int arc_weight = succs[i].second;
		    while(arc_weight >= 100000)
			arc_weight -= 100000;
		    //cout << "Looking at arc from " << removed << " to " << target << endl;
		    int new_weight = heap_positions[target]->first - arc_weight;
		    heap.erase(heap_positions[target]);
		    heap_positions[target] = heap.insert(make_pair(new_weight, target));
		    if(debug)
			cout << "node " << target << " has now " << new_weight << " edges " << endl;
		}
	    }
	}
	if(debug){
	    cout << "result: " << endl;
	    for(uint32_t i = 0; i < result.size(); i++)
		cout << result[i] <<" - ";
	    cout << endl;
	}

    }
    
}


