Cod sursa(job #2564251)

Utilizator trifangrobertRobert Trifan trifangrobert Data 1 martie 2020 19:27:23
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.45 kb
#include <bits/stdc++.h>

using namespace std;

const int NMAX = 2005;
const int KMAX = 18;
const int INF = (1 << 30);
int N, M, K;
int f[KMAX], dist[KMAX][KMAX];
vector < pair <int, int> > graph[NMAX];
int d[NMAX];
int dp[KMAX][1 << KMAX];
bitset <NMAX> seen;
priority_queue < pair <int, int> > pq;

void Dijkstra(int start)
{
    seen.reset();
    for (int i = 1;i <= N;++i)
        d[i] = INF;
    pq.push(make_pair(0, start));
    d[start] = 0;
    while (!pq.empty())
    {
        int node = pq.top().second;
        pq.pop();
        if (seen[node] == 0)
        {
            seen[node] = 1;
            for (auto& x : graph[node])
            {
                int nextnode = x.first, cost = x.second;
                if (d[nextnode] > d[node] + cost)
                {
                    d[nextnode] = d[node] + cost;
                    pq.push(make_pair(-d[nextnode], nextnode));
                }
            }
        }
    }
}

int main()
{
    ifstream fin("ubuntzei.in");
    ofstream fout("ubuntzei.out");
    fin >> N >> M;
    fin >> K;
    int kk = 0;
    for (int i = 1;i <= K;++i)
    {
        int x;
        fin >> x;
        if (x != 1 && x != N)
            f[++kk] = x;
    }
    f[0] = 1;
    ++kk;
    f[kk] = N;
    K = kk;
    for (int i = 1;i <= M;++i)
    {
        int u, v, c;
        fin >> u >> v >> c;
        graph[u].push_back(make_pair(v, c));
        graph[v].push_back(make_pair(u, c));
    }
    for (int i = 0;i <= K;++i)
    {
        Dijkstra(f[i]);
        for (int j = 0;j <= K;++j)
            dist[i][j] = d[f[j]];
    }
    for (int i = 0;i < K;++i)
        for (int state = 0;state < (1 << K);++state)
            dp[i][state] = INF;
    dp[0][1] = 0;
    for (int state = 1;state < (1 << K);++state)
        for (int i = 0;i < K;++i)
            if ((state & (1 << i)) > 0)
                for (int j = 0;j < K;++j)
                    if ((state & (1 << j)) == 0)
                    {
                        int newstate = (state ^ (1 << j));
                        if (dp[i][state] != INF)
                            dp[j][newstate] = min(dp[j][newstate], dp[i][state] + dist[i][j]);
                    }
    int answer = INF;
    for (int i = 0;i < K;++i)
        if (dp[i][(1 << K) - 1] != INF)
            answer = min(answer, dp[i][(1 << K) - 1] + dist[i][K]);
    fout << answer << "\n";
    fin.close();
    fout.close();
    return 0;
}