Pagini recente » Cod sursa (job #979147) | Cod sursa (job #816018) | Cod sursa (job #336821) | Cod sursa (job #2962285) | Cod sursa (job #2308707)
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
using namespace std;
ifstream fin("ubuntzei.in");
ofstream fout("ubuntzei.out");
const int Inf = 0x3f3f3f3f;
using VI = vector<int>;
using VP = vector<pair<int, int>>;
struct Pair{
int node, cost;
bool operator < (const Pair& p) const
{
return cost > p.cost;
}
};
int N, M, K;
VI a; // a - lista nodurilor care trebuie vizitate
vector<VP> G; // G - graful dat
vector<VI> cost; // cost[i][j] = costul dintre a[i] si a[j]
vector<VI> D; // D[mask][i] = costul minim daca merg prin nodurile din mask, ultimul nod vizitat fiind i
priority_queue<Pair> Q;
void ReadData();
void Solve();
void Dyn();
VI Dijkstra(int node); // returneaza un vector reprezentand costurile de la nodul node la oricare alt nod
int main()
{
ReadData();
Solve();
fout << D[(1 << (K - 1)) - 1][K - 1] << '\n';
fin.close();
fout.close();
return 0;
}
void ReadData()
{
fin >> N >> M;
fin >> K;
a = VI(K + 2); ++K;
a[0] = 1;
for (int i = 1; i < K; ++i)
fin >> a[i];
a[K++] = N;
G = vector<VP>(N + 1);
int x, y, z;
while (M--)
{
fin >> x >> y >> z;
G[x].push_back({y, z});
G[y].push_back({x, z});
}
}
void Solve()
{
D = vector<VI>(1 << (K - 1), VI(K, Inf));
cost = vector<VI>(K, VI(K));
for (size_t i = 0; i < a.size() - 1; ++i)
{
VI c = Dijkstra(a[i]);
for (size_t j = i + 1; j < a.size(); ++j)
{
cost[i][j] = cost[j][i] = c[a[j]];
// cout << a[i] << ' ' << a[j] << ' ' << cost[i][j]; cin.get();
}
}
Dyn();
}
void Dyn()
{
D[0][0] = 0;
for (int mask = 1; mask < (1 << (K - 1)); ++mask) // pentru fiecare masca de biti posibila
for (int i = 1; i < K; ++i) // ultimul nod vizitat poate fi doar intre 1 si K ( daca era 0 e cazul initial )
{
if ( !(mask & (1 << (i - 1))) ) // nodul i trebuie sa fie in masca
continue;
if ( !(mask ^ (1 << (i - 1))) ) // daca i e chiar primul nod vizitat
{
D[mask][i] = cost[0][i];
continue;
}
for (int j = 1; j < K; ++j) // caut penultimul posibil nod vizitat
{
if ( !(mask & (1 << (j - 1))) )
continue;
D[mask][i] = min(D[mask][i], D[mask ^ (1 << (i - 1))][j] + cost[i][j]); // si calculez in fuctie de el
}
}
}
VI Dijkstra(int node) // Dijkstra clasic cu priority_queue
{
Q.push({node, 0});
VI c(N + 1, Inf);
c[node] = 0;
while (!Q.empty())
{
int node = Q.top().node;
int cc = Q.top().cost;
Q.pop();
if ( cc != c[node] )
continue;
for (const auto& x : G[node])
{
int next = x.first;
int cost = x.second;
if ( c[next] > c[node] + cost )
{
c[next] = c[node] + cost;
Q.push({next, c[next]});
}
}
}
return c;
}