Pagini recente » Cod sursa (job #285696) | Cod sursa (job #1453310) | Cod sursa (job #811135) | Cod sursa (job #2826958) | Cod sursa (job #2108871)
#include <bits/stdc++.h>
using namespace std;
ifstream fin ("ubuntzei.in");
ofstream fout ("ubuntzei.out");
const short Nmax = 2001;
const int Pmax = (1 << 17) + 1;
const short Kmax = 17;
const int inf = (1 << 30);
int n, m, dp[Pmax][Kmax], k, valmax, cost[Nmax][Nmax], b[Kmax], dist[Nmax];
bitset < Nmax > viz;
vector < pair < int, int > > L[Nmax];
struct Pair
{
int nod, val;
bool operator < (const Pair &e) const
{
return val > e . val;
}
};
priority_queue < Pair > Q;
/**
dp[i][j] - > lungimea minima de la nodul 1 la nodul j trecand prin i valori binare
*/
inline void Read()
{
int x, y, c;
fin >> n >> m;
fin >> k;
for(int i = 1 ; i <= k ; i++)
fin >> b[i];
b[0] = 1;
b[++k] = n;
valmax = (1 << k) - 1;
for(int i = 1 ; i <= m ; i++)
{
fin >> x >> y >> c;
L[x] . push_back({ y, c });
L[y] . push_back({ x, c });
}
for(int i = 0 ; i <= valmax ; i++)
for(int j = 0 ; j <= k ; j++)
dp[i][j] = inf;
for(int i = 1 ; i <= n ; i++)
for(int j = 1 ; j <= n ; j++)
cost[i][j] = inf;
}
inline void Dijkstra(int x)
{
int d, p;
Pair w, w1;
viz . reset();
for(int i = 1 ; i <= n ; i++)
dist[i] = inf;
dist[x] = 0;
w . nod = x;
w . val = 0;
Q . push(w);
while(! Q .empty())
{
w = Q . top();
Q . pop();
if(!viz[w . nod])
{
viz[w . nod] = 1;
for(auto c : L[w . nod])
{
p = c . first;
d = c . second;
if(dist[p] > dist[w . nod] + d)
{
dist[p] = dist[w . nod] + d;
w1 . nod = p;
w1 . val = dist[p];
Q . push(w1);
}
}
}
}
}
inline void Build()
{
for(int i = 0 ; i <= k ; i++)
{
Dijkstra(b[i]);
for(int j = 0 ; j <= k ; j++)
cost[i][j] = dist[b[j]];
}
}
inline void Solve()
{
///Initializari
for(int i = 0 ; i < k ; i++)
dp[1 << i][i] = cost[1][b[i]]; /// numai bitul i este 1 inseamna ca drumul care incepe de la 1 trece numai
/// pe la un singur prieten
for(int i = 0 ; i <= valmax ; i++)
for(int j = 0 ; j <= k ; j++)
if(( i & (1 << j)))
for(int pas = 0 ; pas <= k ; pas++)
if(!(i & (1 << pas)) ) /// nu am trecut pe la al pas-lea prieten
dp[(i | (1 << pas))][pas] = min(dp[(i | (1 << pas))][pas], dp[i][j] + cost[j][pas]);
///cum i are la bitul cu numarul j 1 inseamna ca i | (1 << pas) va avea la bitul cu numarul pas si el tot 1
/// = > trecem si la nodul cu numarul pas (de la nodul cu numarul j)
int sol = inf;
for(int i = 0 ; i < k ; i++)
sol = min(sol, dp[valmax][i] + cost[i][k]);
/// dp[valmax][i] - > costul minim de la nodul cu nr 1 la nodul cu nr i trecand prin toti prietenii
/// (inclusiv nodul 1)
if(k == 0)
fout << cost[1][n] << "\n";
else
fout << sol << "\n";
}
int main()
{
Read();
Build();
Solve();
fin.close();
fout.close();
return 0;
}