Pagini recente » Cod sursa (job #66249) | Cod sursa (job #360157) | Cod sursa (job #2270682) | Cod sursa (job #2550345) | Cod sursa (job #2986158)
#include <iostream>
#include <fstream>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
ifstream fin("ubuntzei.in");
ofstream fout("ubuntzei.out");
/*
Run dijkstra for all friends to condense the graph
Build the new graph
Run configuration dp on the new graph
*/
const int INF = 0x3f3f3f3f;
const int MAX_K = 18;
struct Edge
{
int destination;
int cost;
bool operator < (const Edge& other) const {
return cost > other.cost;
}
};
vector <Edge> graph[2005];
vector <Edge> condensedGraph[MAX_K];
priority_queue <Edge> heap;
int distances[2005];
int friends[MAX_K];
int dp[1 << MAX_K][MAX_K];
int n, m, k;
void Dijkstra(int node) {
Edge firstEdge = {node, 0};
heap.push(firstEdge);
memset(distances, INF, sizeof(distances));
distances[node] = 0;
while (!heap.empty()) {
Edge edge = heap.top();
heap.pop();
for (Edge newEdge : graph[edge.destination]) {
if (distances[newEdge.destination] <= distances[edge.destination] + newEdge.cost) {
continue;
}
distances[newEdge.destination] = distances[edge.destination] + newEdge.cost;
newEdge.cost = distances[newEdge.destination];
heap.push(newEdge);
}
}
}
void BuildCondensedGraph(int friendsCount) {
for (int i = 1; i <= friendsCount; i++) {
int startFriendNode = friends[i];
// Run Dijkstra for all friends
Dijkstra(startFriendNode);
for (int j = i + 1; j <= friendsCount; j++) {
int finishFriendNode = friends[j];
int distance = distances[finishFriendNode];
// Build the condensed graph
Edge condensedGraphEdge = {j, distance};
condensedGraph[i].push_back(condensedGraphEdge);
condensedGraphEdge = {i, distance};
condensedGraph[j].push_back(condensedGraphEdge);
}
}
}
void BuildDynamicConfiguration(int nodesCount) {
memset(dp, INF, sizeof(dp));
dp[1][1] = 0;
for (int conf = 1; conf < (1 << (nodesCount + 1)); conf += 2) {
for (int node = 1; node <= nodesCount; node++) {
if (dp[conf][node] == INF) {
continue;
}
for (Edge edge : condensedGraph[node]) {
// Check if it was visited
if (conf & (1 << (edge.destination - 1))) {
continue;
}
// Mark new node in the configuration
int newConf = conf ^ (1 << (edge.destination - 1));
// Update the dp with the min
dp[newConf][edge.destination] = min(dp[newConf][edge.destination], dp[conf][node] + edge.cost);
}
}
}
}
int GetAnswer(int nodesCount) {
return dp[(1 << nodesCount ) - 1][nodesCount];
}
int main() {
fin >> n >> m;
fin >> k;
// Add start
friends[1] = 1;
k++;
for (int i = 2; i <= k; i++) {
fin >> friends[i];
}
for (int i = 1; i <= m; i++) {
int a, b, c;
fin >> a >> b >> c;
Edge graphEdge = {b, c};
graph[a].push_back(graphEdge);
graphEdge = {a, c};
graph[b].push_back(graphEdge);
}
// Add destination
friends[++k] = n;
BuildCondensedGraph(k);
BuildDynamicConfiguration(k);
int answer = GetAnswer(k);
fout << answer << '\n';
return 0;
}