Cod sursa(job #2464784)

Utilizator Anastasia11Susciuc Anastasia Anastasia11 Data 28 septembrie 2019 22:00:55
Problema Ubuntzei Scor 10
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.55 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>
#include <queue>
#define Nmax 2005
#define Kmax 16
#define INF 0x3f3f3f3f
#define pii pair <int, int>

using namespace std;

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

int d[Kmax+2][Nmax]; // distant de la nodul c[i] la j
struct cmp{
    bool operator()(int x, int y)
    {
        return d[x]>d[y];
    }
};

int n, m, k;
int c[Nmax];
bool used[Nmax];
vector <pair <int, int> > v[Nmax];
priority_queue <int, vector <int>, cmp> Q;
int dp[Nmax][(1<<Kmax)]; // dp[i][j]-costul minim pentru a ajunge in orasul i trecand prin orasele
                         // c[x], x - bit de unu din cofiguratia lui j


void read()
{
    f >> n >> m >> k;

    for (int i = 1; i <= k; i++)
        f >> c[i];

    for (int i = 1, x, y, c; i <= m; i++)
    {
        f >> x >> y >> c;
        v[x].push_back({y, c});
        v[y].push_back({x, c});
    }
}

void dijkstra(int start, int d[])
{
    d[start]=0;
    Q.push(start);
    memset(used, 0, sizeof(used));
    used[start]=1;
    while (!Q.empty())
    {
        int x=Q.top();
        Q.pop();
        for (int k = 0; k < v[x].size(); k++)
        {
            int y=v[x][k].first;
            int cost=v[x][k].second;
            if (d[x]+cost < d[y])
            {
                d[y]=d[x]+cost;
                if (!used[y])
                {
                    used[y]=1;
                    Q.push(y);
                }
            }
        }
    }

}

void build_dist()
{
    memset(d, INF, sizeof(d));
    dijkstra(1, d[1]);
    for (int i = 1; i <= k; i++)
        dijkstra(c[i], d[c[i]]);

    dijkstra(n, d[n]);

}

void solve()
{
    if (k == 0) g << d[1][n];
    else
    {
        for (int i = 1; i <= k; i++)
            dp[i][1 << (i - 1)] = d[1][c[i]];

        for (int i = 1; i < (1<<k); i++)
            for (int j = 1; j <= k; j++)
            {
                if (i & (1<<(j-1)))
                {
                    for (int l = 1; l <= k; l++)
                    {
                        if (j == l) continue;
                        if (i & (1 << (l - 1)))
                            dp[j][i] = min(dp[j][i], dp[l][i ^ (1 << (j - 1))] + d[c[j]][c[l]]);
                    }
                }
            }

        int ans = INF;
        for (int i = 1; i <= k; i++)
            ans = min(ans, dp[i][(1<<k)-1] + d[n][c[i]]);
        g << ans;
    }
}

int main()
{
    read();
    build_dist();
    solve();
    return 0;
}