Cod sursa(job #2935494)

Utilizator Andrei_ierdnANeculau Rares-Andrei Andrei_ierdnA Data 6 noiembrie 2022 19:39:05
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.7 kb
#include <fstream>
#include <vector>
#include <queue>

using namespace std;

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

int n, m, k, c[17], i, j, x, y, z, dist[18][2010], mi;
vector<pair<int, int>> nb[2010];
vector<pair<int, int>>::iterator it;
priority_queue<pair<int, int>> dq;
const int INF = 200000000;
int edges[19][19];
int dp[19][140100];
bool iscalc[19][140100];

void dijkstra(int start)
{
    for (i = 1; i <= n; i++) {
        if (i != start) {
            dist[mi][i] = INF;
            dq.push({-INF, i});
        }
        else {
            dist[mi][i] = 0;
            dq.push({0, i});
        }
    }
    while (!dq.empty())
    {
        i = dq.top().second;
        if (dist[mi][i] != -dq.top().first) {
            dq.pop();
        }
        else {
            if (dist[mi][i] == INF) {
                while (!dq.empty())
                    dq.pop();
            }
            else {
                dq.pop();
                for (it = nb[i].begin(); it != nb[i].end(); advance(it, 1))
                {
                    if (dist[mi][(it->first)] > dist[mi][i] + (it->second)) {
                        dist[mi][(it->first)] = dist[mi][i] + (it->second);
                        dq.push({-dist[mi][(it->first)], (it->first)});
                    }
                }
            }
        }
    }
}

int calcDP(int node, int mask)
{
    if (iscalc[node][mask])
        return dp[node][mask];
    int mask2 = (mask ^ (1 << (node-2)));
    if (!mask2) {
        dp[node][mask] = edges[1][node];
    }
    else {
        for (int i = 0; i < (k+1); i++)
        {
            if ((mask2 & (1<<i)))
            {
                dp[node][mask] = min(dp[node][mask], calcDP(i+2, mask2) + edges[i+2][node]);
            }
        }
    }
    iscalc[node][mask] = true;
    return dp[node][mask];
}

int main()
{
    f >> n >> m >> k;
    for (i = 1; i <= k; i++)
        f >> c[i];
    for (i = 1; i <= m; i++) {
        f >> x >> y >> z;
        nb[x].push_back({y, z});
        nb[y].push_back({x, z});
    }
    /// 17 dijkstra si un hamilton
    /// cine, eu? copy-paste? niciodata
    mi = 1;
    dijkstra(1);
    mi = k+2;
    dijkstra(n);
    for (mi = 2; mi <= k+1; mi++)
        dijkstra(c[mi-1]);
    for (i = 1; i <= k+2; i++) {
        edges[i][1] = dist[i][1];
        edges[i][k+2] = dist[i][n];
        for (j = 2; j <= k+1; j++)
            edges[i][j] = dist[i][c[j-1]];
    }
    for (i = 1; i <= k+2; i++)
        for (j = 0; j < (1<<(k+1)); j++)
            dp[i][j] = INF;
    dp[1][0] = 0;
    iscalc[1][0] = true;
    g << calcDP(k+2, (1<<(k+1))-1);
    f.close();
    g.close();
    return 0;
}