Cod sursa(job #2649675)

Utilizator blackmanta45Andrei blackmanta45 Data 15 septembrie 2020 19:33:02
Problema Ubuntzei Scor 25
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 5.51 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <string.h>
#include <climits>
#define INF 1000000000000000
using namespace std;
ifstream fin("ubuntzei.in");
ofstream fout("ubuntzei.out");

int i, n, m, T, air, k, start, ending, cost, treasure_location[20], j, no_Treasures, start_treasure;
long long  dist[10010], stack[10010];
int isTreasure[10010];
bool isNode[10010];
long long C[10025][20];
long long Cost[20][20];
vector<int> nodes;
vector<pair<int, int>> bigGraph[50001];
vector<int> smallGraph[20];

bool cmd(int a, int b) {
    if (a < b)
        return 1;
    return 0;
}

void dijkstra(int start) {
    //vector<pair<int, int>> bigGraph[10001];
    long long st, dr;
    bool visited[10010] = { 0 };
    for (unsigned int i = 0; i < nodes.size(); i++) {
        dist[nodes[i]] = INF;
    }
    dist[start] = 0;
    stack[0] = start;
    int startNodeSmall = isTreasure[start];
    st = dr = 0;
    while (st <= dr) {
        for (auto node : bigGraph[stack[st]]) {
            if (!visited[node.first]) {
                if (node.second + dist[stack[st]] < dist[node.first]) {
                    long long prev_value = dist[node.first];
                    dist[node.first] = node.second + dist[stack[st]];
                    int currentSmallNode = isTreasure[node.first];
                    if (currentSmallNode || node.first == 0) {
                        if (prev_value == INF) {
                            smallGraph[startNodeSmall].push_back(currentSmallNode);
                            Cost[startNodeSmall][currentSmallNode] = dist[node.first];
                        }
                        else {
                            for (auto nodeToUpdate : smallGraph[startNodeSmall])
                                if (nodeToUpdate == currentSmallNode) {
                                    Cost[startNodeSmall][nodeToUpdate] = dist[node.first] < Cost[startNodeSmall][nodeToUpdate] ? dist[node.first] : Cost[startNodeSmall][nodeToUpdate];
                                    break;
                                }
                        }
                    }
                    stack[++dr] = node.first;
                }
            }
            else {
                if (node.second + dist[stack[st]] < dist[node.first]) {
                    long long prev_value = dist[node.first];
                    dist[node.first] = node.second + dist[stack[st]];
                    int currentSmallNode = isTreasure[node.first];
                    if (currentSmallNode || node.first == 0) {
                        if (prev_value == INF) {
                            smallGraph[startNodeSmall].push_back(currentSmallNode);
                            Cost[startNodeSmall][currentSmallNode] = dist[node.first];
                        }
                        else {
                            for (auto nodeToUpdate : smallGraph[startNodeSmall])
                                if (nodeToUpdate == currentSmallNode) {
                                    Cost[startNodeSmall][nodeToUpdate] = dist[node.first] < Cost[startNodeSmall][nodeToUpdate] ? dist[node.first] : Cost[startNodeSmall][nodeToUpdate];
                                    break;
                                }
                        }
                    }
                }
            }
        }
        visited[stack[st]] = 1;
        st++;
    }
    //sort(smallGraph[isTreasure[start]].begin(), smallGraph[isTreasure[start]].end(), cmd);
}

void HamiltonianCicle() {
    no_Treasures+=2;
    int pow2 = 1 << no_Treasures;
    for (int i = 0; i < pow2; ++i) {
        for (int j = 0; j < no_Treasures; ++j) {
            C[i][j] = INF;
        }
    }
    C[1][0] = 0;
    for (int i = 0; i < pow2; i++) {
        for (int j = no_Treasures - 1; j >= 0; --j) {
            if (i & (1 << j)) {
                for (size_t k = 0; k < smallGraph[j].size(); ++k) {
                    if (i & (1 << smallGraph[j][k])) {
                        C[i][j] = min(C[i][j], 1LL * C[i ^ (1 << j)][smallGraph[j][k]] + Cost[smallGraph[j][k]][j]);
                    }
                    C[i][j] = min(C[i][j], 1LL * C[i][smallGraph[j][k]] + Cost[smallGraph[j][k]][j]);
                }
            }
        }
    }
}

int getNoOf1(int n) {
    int count = 0;
    for (int i = 0; i < 17; i++) {
        if (n & (1 << i))
            count++;
    }
    return count - 1;
}

int main() {
    fin >> n >> m;

    fin >> no_Treasures;
    start_treasure = 0;
    for (i = 0; i < no_Treasures; i++) {
        fin >> treasure_location[i];
        treasure_location[i]--;
        isTreasure[treasure_location[i]] = i + 1;
    }
    isTreasure[n - 1] = i + 1;
    for (i = 0; i < m; i++) {
        fin >> start >> ending >> cost;
        start--;
        ending--;
        bigGraph[start].push_back(make_pair(ending, cost));
        bigGraph[ending].push_back(make_pair(start, cost));
        if (!isNode[start])
            nodes.push_back(start), isNode[start] = 1;
        if (!isNode[ending])
            nodes.push_back(ending), isNode[ending] = 1;
    }
    
    isTreasure[0] = 0;
    //fin >> air;
    for (i = 0; i <= 14; i++)
        for (j = 0; j <= 14; j++)
            Cost[i][j] = INF;
    dijkstra(0);
    for (i = 0; i < no_Treasures; i++) {
        dijkstra(treasure_location[i]);
    }
    dijkstra(n-1);
    long long solution = 100000000;
    HamiltonianCicle();
    int pow2 = 1 << (no_Treasures+2);
    
    fout << C[(1 << no_Treasures) - 1][isTreasure[n - 1]];
}