Cod sursa(job #1355084)

Utilizator hohoho97Valentin Nita hohoho97 Data 22 februarie 2015 12:55:37
Problema Ubuntzei Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.55 kb
#include <fstream>

#include <vector>
#include <queue>
#include <set>

#include <utility>

using namespace std;

class Edge
{
private:
	unsigned i, j;
	double w;

public:
	Edge();
	Edge(unsigned, unsigned, double = 0.0);
	unsigned one() const;
	unsigned other(unsigned) const;
	double weight() const;
	bool operator< (const Edge&) const;
};

Edge::Edge()
{
	this->i = 0;
	this->j = 0;
	this->w = 0;
}

Edge::Edge(unsigned start, unsigned end, double weight)
{
	this->i = start;
	this->j = end;
	this->w = weight;
}

unsigned Edge::one() const
{
	return this->i;
}

unsigned Edge::other(unsigned one) const
{
	if (one == this->i)
		return this->j;
	else if (one == this->j)
		return this->i;
	else
		return -1;
}

double Edge::weight() const
{
	return this->w;
}

bool Edge::operator< (const Edge& another) const
{
	return this->w < another.weight();
}

class WGraph
{
private:
	vector<multiset<Edge>> vertices;

public:
	WGraph(unsigned = 1024);
	unsigned size() const;
	void edge(unsigned, unsigned, double);
	const multiset<Edge>& adj(unsigned) const;
	unsigned degree(unsigned) const;
};

WGraph::WGraph(unsigned vertices)
{
	this->vertices.resize(vertices + 1);
}

unsigned WGraph::size() const
{
	return this->vertices.size();
}

void WGraph::edge(unsigned v1, unsigned v2, double w)
{
	this->vertices.at(v1).insert(Edge(v1, v2, w));
	this->vertices.at(v2).insert(Edge(v2, v1, w));
}

const multiset<Edge>& WGraph::adj(unsigned vertex) const
{
	return this->vertices.at(vertex);
}

unsigned WGraph::degree(unsigned vertex) const
{
	return this->vertices.at(vertex).size();
}

class Ubuntzei
{
public:
	Ubuntzei()
	{
		ifstream in("ubuntzei.in");

		in >> n >> m >> k;

		orase.resize(k);

		for (auto& oras : orase)
		{
			in >> oras;
		}

		wg = new WGraph(n);

		int a, b, c;
		for (int i = 0; i < m; i++)
		{
			in >> a >> b >> c;
			wg->edge(a, b, c);
		}

		in.close();

		double sum = 0;
		int curent = 1;
		while (!orase.empty())
		{
			double minim = diskstra(curent, orase.front());
			int index = 0;

			for (int i = 1; i < orase.size(); i++)
			{
				double c = diskstra(curent, orase[i]);
				if (c < minim)
				{
					minim = c;
					index = i;
				}
			}

			curent = orase[index];
			sum += minim;
			orase.erase(orase.begin() + index);
		}

		ofstream out("ubuntzei.out");

		out << sum + diskstra(curent, n) << endl;

		out.close();
	}

private:
	double diskstra(int start, int end)
	{
		dist.assign(n + 1, numeric_limits<double>::infinity());
		from.assign(n + 1, Edge());

		dist[start] = 0.0;

		priority_queue<pair<double, int>, vector<pair<double, int>>, comp> pq;
		pq.push(make_pair(0.0, start));

		vector<bool> marked(n + 1, false);
		while (!pq.empty())
		{
			int vertex = pq.top().second;
			pq.pop();

			if (!marked[vertex])
			{
				for (const Edge& e : wg->adj(vertex))
				{
					int v = e.other(vertex);
					if (dist[vertex] + e.weight() < dist[v])
					{
						dist[v] = dist[vertex] + e.weight();
						from[v] = e;
						pq.push(make_pair(dist[v], e.other(vertex)));
					}
				}

				marked[vertex] = true;
			}
		}

		double sum = 0;
		int vertex = end;
		Edge curent = from[end];
		while (vertex != start)
		{
			sum += curent.weight();
			vertex = curent.other(vertex);
			curent = from[vertex];
		}

		return sum;
	}

private:
	int n, m, k;

	vector<int> orase;

	WGraph* wg;
	vector<double> dist;
	vector<Edge> from;
};

int main()
{
	Ubuntzei();

	return 0;
}