Cod sursa(job #2466245)

Utilizator Briana_NeaguNeagu Briana Briana_Neagu Data 1 octombrie 2019 19:36:04
Problema Ubuntzei Scor 25
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.28 kb
#include <bits/stdc++.h>
#define nmax 2005
#define kmax 15
#define oo (1 << 30)

using namespace std;

ifstream f("ubuntzei.in");
ofstream g("ubuntzei.out");

vector <int> friends;
vector <pair <int, int >> vec[nmax];

struct cmp
{
    bool operator() (const pair <int, int> &a, const pair <int, int> &b) const
    {
        return a.second > b.second;
    }
};

priority_queue <pair <int, int>, vector<pair <int, int> >, cmp > heap;
int lungime[nmax][nmax];

void dijkstra(const int first, const int n)
{
    for (int i = 0; i < n; ++ i)
        if (first != i)
            lungime[first][i] = oo;
    heap.push({first, 0});
    while (!heap.empty())
    {
        pair <int, int> now = heap.top();
        heap.pop();
        if (now.second != lungime[first][now.first])
            continue;

        for (auto next : vec[now.first])
            if (lungime[first][next.first] > now.second + next.second)
            {
                lungime[first][next.first] = now.second + next.second;
                heap.push({next.first, now.second + next.second});
            }
    }
}

int dp[kmax << 1][kmax];

int main()
{
    int n, m, k;
    f >> n >> m >> k;
    for (int i = 0; i < k; ++ i)
    {
        int x;
        f >> x;
        x --;
        friends.push_back(x);
    }
    while (m --)
    {
        int x, y, z;
        f >> x >> y >> z;
        x --;
        y --;
        vec[x].emplace_back(y, z);
        vec[y].emplace_back(x, z);
    }
    dijkstra(0, n); // pentru inceput
    if (k == 0)
    {
        g << lungime[0][n - 1];
        return 0;
    }
    for (auto el : friends)
        dijkstra(el, n);

    for (int i = 0; i < k; ++ i)
        dp[1 << i][i] = lungime[0][friends[i]];

    for (int mask = 1; mask < (1 << k); ++ mask)
        for (int last = 0; last < k; ++ last)
            if (mask & (1 << last))
                for (int now = 0; now < k; ++ now)
                    if (!(mask & (1 << now)))
                        if ( dp[mask | (1 << now)][now] == 0 || dp[mask | (1 << now)][now] > dp[mask][last] + lungime[friends[last]][friends[now]])
                            dp[mask | (1 << now)][now] = dp[mask][last] + lungime[friends[last]][friends[now]];

    int ans = oo;
    for (int i = 0; i < k; ++ i)
        ans = min(ans, dp[(1 << k) - 1][i] + lungime[friends[i]][n - 1]);
    g << ans;
}