Pagini recente » Cod sursa (job #1622318) | Cod sursa (job #1518129) | Cod sursa (job #2157944) | Cod sursa (job #3239278) | Cod sursa (job #1355086)
#include <fstream>
#include <vector>
#include <queue>
#include <set>
#include <limits>
#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;
}