Cod sursa(job #2061210)

Utilizator TudoseSanzianaTudose Sanziana TudoseSanziana Data 8 noiembrie 2017 23:23:14
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.34 kb
#include <bits/stdc++.h>
using namespace std;

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

const int NMAX = 2e3, KMAX = 15, INF = 2e9, CONF = (1<<16);

struct EDGE
{
    int y, cost;
    bool operator <(const EDGE &aux) const{
        return cost > aux.cost;
    }
};

int n, m, k;
vector<EDGE> gr[NMAX + 5];
int loc[KMAX + 5], vis[NMAX + 5];
int dist[NMAX + 5][NMAX + 5];

int ans;
int dp[KMAX + 5][CONF + 5];

void dijkstra(int node);

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

    in >> k;
    for(int i=0; i<k; i++)
        in >> loc[i];

    while(m--)
    {
        int x, y, cost;
        in >> x >> y >> cost;

        gr[x].push_back({y,cost});
        gr[y].push_back({x,cost});
    }

    dijkstra(1);
    for(int i=0; i<k; i++)
        dijkstra(loc[i]);

    if(k == 0)
    {
        out << dist[1][n] << '\n';
        return 0;
    }

    /// ***

    int maxStare = (1 << k) - 1;

    for(int stare = 1; stare <= maxStare; stare++)
        for(int i=0; i<k; i++)
            dp[i][stare] = INF;

    for(int i=0; i<k; i++)
    {
        dp[i][(1 << i)] = dist[1][loc[i]];
        dp[i][0] = dist[1][loc[i]];
    }

    for(int stare = 1; stare <= maxStare; stare++)
    {
        for(int i=0; i<k; i++)
            if(stare & (1 << i))
            {
                for(int j=0; j<k; j++)
                    if(stare & (1 << j))
                        dp[i][stare] = min(dp[i][stare], dp[j][stare - (1 << i)] + dist[loc[i]][loc[j]]);
            }
    }

    ans = INF;
    for(int i=0; i<k; i++)
        if(dp[i][maxStare] != INF)
            ans = min(ans, dp[i][maxStare] + dist[loc[i]][n]);

    out << ans << '\n';

    return 0;
}

void dijkstra(int node)
{
    for(int i=1; i<=n; i++)
    {
        dist[node][i] = INF;
        vis[i] = false;
    }

    priority_queue<EDGE> pq;

    dist[node][node] = 0;
    pq.push({node, 0});
    while(!pq.empty())
    {
        EDGE fr = pq.top();

        if(!vis[fr.y])
        {
            for(auto it: gr[fr.y])
                if(dist[node][it.y] > dist[node][fr.y] + it.cost)
                {
                    dist[node][it.y] = dist[node][fr.y] + it.cost;
                    pq.push({it.y, dist[node][it.y]});
                }
            vis[fr.y] = true;
        }

        pq.pop();
    }
}