Pagini recente » Cod sursa (job #3303592) | Monitorul de evaluare | Cod sursa (job #3344453) | Cod sursa (job #3347590) | Cod sursa (job #3341208)
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <map>
using namespace std;
#define in fin
#define out fout
ifstream fin("ubuntzei.in");
ofstream fout("ubuntzei.out");
typedef pair<int, int> pii;
const int MAXN = 2e3;
const int MAXM = 1e4;
const int MAXK = 17; // hmm
const int INF = 1e9;
int n, m, kc, cx, x, y, z, dmin;
int orase[MAXK+1];
int st[MAXN+1];
int dp[1 << MAXK][MAXK+1]; // dp[mask][i] = distanta minima pana in nodul oras[i] vizitand nodurile cu biti 1 din masca
vector<pii> graf[MAXN+1];
vector<vector<int>> distante(MAXN+2, vector<int>(MAXN+2, INF));
void citire();
void dijkstra(int init, vector<int> &dist) {
priority_queue<pii, vector<pii>, greater<pii>> pq;
dist[init] = 0;
pq.push({ 0, init });
while (!pq.empty()) {
int nod = pq.top().second;
int distInit = pq.top().first;
pq.pop();
if (distInit > dist[nod])
continue;
for (auto e: graf[nod]) {
int nodExt = e.first;
int cost = e.second;
if (dist[nodExt] > dist[nod] + cost) {
dist[nodExt] = dist[nod] + cost;
pq.push({ dist[nodExt], nodExt });
}
}
}
}
int main() {
citire();
dijkstra(1, distante[1]);
for (int i = 1; i <= kc; i++)
dijkstra(orase[i], distante[ orase[i] ]);
orase[0] = 1;
orase[kc + 1] = n;
int max_mask = 1 << kc;
// distantele se initializeaza cu INF
for (int mask = 0; mask < max_mask; mask++)
for (int j = 0; j <= kc + 1; j++)
dp[mask][j] = INF;
dp[0][0] = 0; // base case; din orase[0] nu am parcurs niciun oras
for (int mask = 0; mask < max_mask; mask++) {
for (int nod = 0; nod <= kc; nod++) {
// incercam sa vizitam unul dintre orasele necesare
for (int e = 1; e <= kc; e++) {
int bit = e - 1;
// verificam daca nu l-am vizitat deja in masca
if ( (mask & (1 << bit)) == 0 ) {
long long dist = dp[mask][nod] + distante[ orase[nod] ][ orase[e] ];
int maskadd = mask | (1 << bit);
if (dp[maskadd][e] > dist)
dp[maskadd][e] = dist;
}
}
// sau mergem direct la ultimul oras N
long long distN = dp[mask][nod] + distante[ orase[nod] ][ orase[kc + 1] ];
if (dp[mask][kc + 1] > distN)
dp[mask][kc + 1] = distN;
}
}
// rezultatul pe care il cautam este basically dp[masca_full_biti_1][n],
// intrucat vrem sa fi trecut prin toate orasele necesare (toti bitii din masca trb sa fie 1)
out << dp[max_mask - 1][kc + 1];
return 0;
}
void citire() {
in >> n >> m >> kc;
for (int i = 1; i <= kc; i++)
in >> orase[i];
for (int i = 1; i <= m; i++) {
in >> x >> y >> z;
graf[x].push_back({y, z});
graf[y].push_back({x, z});
}
}