int main(int argc, char *argv[]) {
	unsigned int n = 0;
	double beta = 0.0;
	bool verbose = false, correggi = false, shortest = false, l1 = false, l2 = false, linf = false, endpoint = false, interval = false;
	w_type maxPeso = 100000;
	string outfile = "";
	istringstream converter;
	GrafoNonOrientatoBetaMetrico_ListaArchi< w_type > grafo;
	TSPInstance< w_type > problema;
	TSPWriter< w_type > *writer;

	ArgumentList args = ArgumentList(argc, argv);

	if ( argc < 7 || argc > 9 ) {
		cerr << "Utilizzo: " << args.getFirst() << " [-c] [-v] [-s|-e|-l1|-l2|-li] -n <nodi> -b <beta> <outfile>" << endl;
		cerr << "\t-c\t : correggi se non beta metrico;" << endl;
		cerr << "\t-i\t : metrica intervallo (base, base*2beta);" << endl;
		cerr << "\t-s\t : metrica shortest path;" << endl;
		cerr << "\t-e\t : metrica endpoint;" << endl;
		cerr << "\t-l1\t : metrica spazio l1;" << endl;
		cerr << "\t-l2\t : metrica spazio l2;" << endl;
		cerr << "\t-li\t : metrica spazio linf;" << endl;
		cerr << "\t-v\t : verboso." << endl << endl;
		return -1;
	}
	else {
		cout << args.getFirst() << endl;
	}

	verbose = args.getSwitch("-v");
	correggi = args.getSwitch("-c");
	shortest = args.getSwitch("-s");
	interval = args.getSwitch("-i");
	endpoint = args.getSwitch("-e");
	l1 = args.getSwitch("-l1");
	l2 = args.getSwitch("-l2");
	linf = args.getSwitch("-li");
	converter.str(args.getSwitchArgument("-n"));
	converter >> n;
	converter.clear();
	converter.str(args.getSwitchArgument("-b"));
	converter >> beta;

	if ( n < 2 || beta < 0.5 ) {
		cerr << "Il numero di nodi del grafo dev'essere maggiore di 2 ed il valore di beta >= 0.5" << endl;
		return -1;
	}

	outfile = args.getFirst();

	grafo.clear();
	problema.clear();
	grafo.setBeta(beta);

	srand(time(NULL));

	if ( interval ) {
		/* Metrica intervall (base, base*2beta) */

		grafo.generaRandom(n);
	}
	else if ( shortest ) {
		/* Metrica shortest path */

		for ( unsigned int i(0); i < n; i++ ) {
			vertice *temp = grafo.aggiungiVertice();
			temp->setKey(i);
		}

		for ( Grafo< w_type >::vertice_iterator x = grafo.lista_vertici.begin(); x != --(grafo.lista_vertici.end()); x++ ) {
			Grafo< w_type >::vertice_iterator temp = x;
			for ( Grafo< w_type >::vertice_iterator y = ++temp; y != grafo.lista_vertici.end(); y++ ) {
				grafo.aggiungiArco(*x, *y, static_cast< w_type >(1.0 + (maxPeso * (rand() / (RAND_MAX + 1.0)))));
			}
		}

		map< pair<vertice*, vertice*>, w_type > distanze = FloydWarshall(grafo);

		for ( Grafo< w_type >::vertice_iterator x = grafo.lista_vertici.begin(); x != --(grafo.lista_vertici.end()); x++ ) {
			Grafo< w_type >::vertice_iterator temp = x;
			for ( Grafo< w_type >::vertice_iterator y = ++temp; y != grafo.lista_vertici.end(); y++ ) {
				if ( distanze[pair<vertice*, vertice*>(*x, *y)] < grafo.getPesoArcoCompreso(*x, *y) ) {
					(grafo.getArcoCompreso(*x, *y))->costo = distanze[pair<vertice*, vertice*>(*x, *y)];
				}
			}
		}
	}
	else if ( endpoint ) {
		/* Metrica endpoint */

		double beta = grafo.getBeta();
		double betaC = (pow(beta, 2.0) - pow(1 - beta, 2.0)) / (beta * (1 - beta));
		double betaN = (1 - beta) / beta;
		double betaNx = beta / (1 - beta);
		arco< w_type > *tempArco = 0, *minArco = 0, *maxArco = 0;

		for ( unsigned int i(0); i < n; i++ ) {
			vertice *temp = grafo.aggiungiVertice();
			temp->setKey(i);
		}

		for ( Grafo< w_type >::vertice_iterator x = grafo.lista_vertici.begin(); x != --(grafo.lista_vertici.end()); x++ ) {
			bool first = true;
			Grafo< w_type >::vertice_iterator temp = x;
			for ( Grafo< w_type >::vertice_iterator y = ++temp; y != grafo.lista_vertici.end(); y++ ) {
				double Bmin = (2 * pow(beta, 2.0)) / (1 - beta);
				double Bmax = (1 - beta) / (2 * pow(beta, 2.0));

				if (  y == ++(grafo.lista_vertici.begin()) && x == grafo.lista_vertici.begin() ) {
					tempArco = grafo.aggiungiArco(*x, *y, static_cast< w_type >(1.0 + (maxPeso * (rand() / (RAND_MAX + 1.0)))));
					minArco = tempArco;
					maxArco = tempArco;
				}
				else {
					tempArco = grafo.aggiungiArco(*x, *y, static_cast< w_type >(1.0 + (maxPeso * (rand() / (RAND_MAX + 1.0)))));
					tempArco->costo = static_cast< w_type >((tempArco->costo * betaC) + betaN);
					if ( first ) {
						Grafo< w_type >::vertice_iterator tempVertice = x;
						tempArco->costo *= grafo.getPesoArcoCompreso(*(--tempVertice), *x);
						first = false;
					}
					else {
						Grafo< w_type >::vertice_iterator tempVertice = y;
						tempArco->costo *= grafo.getPesoArcoCompreso(*x, *(--tempVertice));
					}

					if ( grafo.sonoArchiAdiacenti(tempArco, minArco) ) {
						Bmin = betaNx;
					}
					if ( grafo.sonoArchiAdiacenti(tempArco, maxArco) ) {
						Bmax = betaN;
					}

					if ( tempArco->costo > (Bmin * minArco->costo) || tempArco->costo < (Bmax * maxArco->costo) ) {
						tempArco->costo = static_cast< w_type >(floor((Bmax * maxArco->costo) + (((Bmin * minArco->costo) - (Bmax * maxArco->costo)) * (rand() / (RAND_MAX + 1.0)))));
					}

					if ( tempArco-> costo > maxArco->costo ) {
						maxArco = tempArco;
					}
					if ( tempArco->costo < minArco->costo ) {
						minArco = tempArco;
					}
				}
			}
		}
	}
	else {
		Space< w_type > spazio;
		map< vertice *, Point * > verticeToPoint;

		for ( unsigned int i(0); i < n; i++ ) {
			vertice *temp = grafo.aggiungiVertice();
			temp->setKey(i);
			verticeToPoint[temp] = spazio.addPoint(static_cast< w_type >(1.0 + (maxPeso * (rand() / (RAND_MAX + 1.0)))), static_cast< w_type >(1.0 + (maxPeso * (rand() / (RAND_MAX + 1.0)))));
		}

		for ( Grafo< w_type >::vertice_iterator v = grafo.lista_vertici.begin(); v != --(grafo.lista_vertici.end()); v++ ) {
			Grafo< w_type >::vertice_iterator temp = v;
			for ( Grafo< w_type >::vertice_iterator u = ++temp; u != grafo.lista_vertici.end(); u++ ) {
				if ( l1 ) {
					/* Metrica spazio l1 */
					grafo.aggiungiArco(*v, *u, static_cast< w_type >(spazio.l1Distance(verticeToPoint[*v], verticeToPoint[*u])));
				}
				else if ( l2 ) {
					/* Metrica spazio l2 */
					grafo.aggiungiArco(*v, *u, static_cast< w_type >(spazio.l2Distance(verticeToPoint[*v], verticeToPoint[*u])));
				}
				else if ( linf ) {
					/* Metrica spazio linf */
					grafo.aggiungiArco(*v, *u, static_cast< w_type >(spazio.lInfDistance(verticeToPoint[*v], verticeToPoint[*u])));
				}
			}
		}
	}

	if ( verbose ) {
		cout << "Grafo generato con n = " << grafo.numVertici() << " ed m = " << grafo.numArchi() << endl;
	}

	if ( correggi ) {
		while ( !grafo.verifyBetaMetric(correggi) ) {};
		if ( verbose ) {
			cout << "Il grafo è risultato " << grafo.getBeta() << "-metrico." << endl;
		}
	}

	problema.setProblemType("TSP");
	problema.setEdgeWType("EXPLICIT");
	problema.setEdgeWFormat("UPPER_ROW");
	problema.setGrafo(&grafo);

	writer = new TSPWriter< w_type >(&problema);
	writer->setOutputFile(outfile);
	if ( !writer->write() ) {
		cerr << "Si e' verificato un problema durante il salvataggio dell'istanza su file." << endl;
		delete writer;
		return 1;
	}
	delete writer;

	if ( verbose ) {
		cout << "L'istanza e' stata salvata in " << outfile << endl;
	}

	return 0;
}
int main(int argc, char *argv[]) {
	bool verbose = false;
	unsigned int intervalli = 10;
	/* Argomenti passati all'eseguibile */
	ArgumentList args = ArgumentList(argc, argv);

	if ( argc < 4 || argc > 5 ) {
		cerr << "Utilizzo: " << args.getFirst() << " [-v] -k <intervalli> <file_istanza_tsp>" << endl;
		cerr << "\t-k: numero di intervalli;" << endl;
		cerr << "\t-v : verboso." << endl << endl;
		return -1;
	}
	else {
		cout << endl << args.getFirst() << endl << endl;
	}

	/* Istanza del problema */
	TSPInstance< w_type > *problema = new TSPInstance< w_type >;
	/* Loader dell'istanza */
	TSPReader< w_type > *reader = new TSPReader< w_type >(problema);
	/* Nome del file da cui caricare l'istanza */
	string filename = "";
	istringstream converter;

	verbose = args.getSwitch("-v");
	converter.str(args.getSwitchArgument("-k"));
	converter >> intervalli;
	filename = args.getFirst();

	reader->setInputFile(filename);

	if ( ! reader->read() ) {
		cerr << "Impossibile leggere l'istanza." << endl;
		delete problema;
		delete reader;
		return -1;
	}

	if ( verbose ) {
		cout << "Istanza caricata, sta per essere eseguito l'algoritmo di calcolo della distribuzione dei pesi." << endl;
	}

	/* Mappa contenente gli intervalli di distribuzione dei pesi e le percentuali */
	map< double, double > *distribuzione = new map< double, double >();
	/* Dimensioni di un intervallo */
	double dimBlocco = 0;
	/* Peso minimo e massimo di un arco */
	w_type min = std::numeric_limits< w_type >::max(), max = std::numeric_limits< w_type >::min();

	for ( Grafo< w_type >::arco_const_iterator e = (problema->getGrafo())->lista_archi.begin(); e != (problema->getGrafo())->lista_archi.end(); e++ ) {
		if ( (*e)->costo < min ) {
			min = (*e)->costo;
		}

		if ( (*e)->costo > max ) {
			max = (*e)->costo;
		}
	}

	if ( verbose ) {
		cout << "Il peso minimo di un arco e' " << min << " mentre il peso massimo e' " << max << endl;
	}

	dimBlocco = (max - min) / static_cast< double >(intervalli);

	for ( unsigned int i(0); i <= intervalli; i++ ) {
		distribuzione->insert(pair< double, unsigned int >(min + (i * dimBlocco), 0));
	}

	for ( Grafo< w_type >::arco_const_iterator e = (problema->getGrafo())->lista_archi.begin(); e != (problema->getGrafo())->lista_archi.end(); e++ ) {
		for ( unsigned int i(1); i <= intervalli; i++ ) {
			if ( min + (i * dimBlocco) > (*e)->costo ) {
				((distribuzione->find(min + ((i - 1) * dimBlocco)))->second)++;
				break;
			}
		}
	}

	for ( map< double, double >::iterator i = (distribuzione->begin())++; i != distribuzione->end(); i++ ) {
		(*i).second = static_cast< double >(((*i).second * 100)) / (problema->getGrafo())->numArchi();
	}

	cout << endl;
	for ( map< double, double >::iterator i = (distribuzione->begin())++; i != --(distribuzione->end()); i++ ) {
		cout << fixed << setprecision (2) << "Da " << (*(--i)).first << " a " << (*(++i)).first << ": " << (*i).second << "%" << endl;
	}
	cout << endl;

	return 0;
}