Cod sursa(job #1621786)

Utilizator radarobertRada Robert Gabriel radarobert Data 29 februarie 2016 21:42:40
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.42 kb
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
#include <iostream>

using namespace std;

const int INF = 0x3f3f3f3f;

priority_queue< pair<int, int> > pq;
queue<pair <int, int> > q;
vector<int> g[2002];
vector<int> cost[2002];
int d[17][2002];
int friends[20];
int df[20][20];
bool vis[17][2002];
int config1[17][131075], config2[17][131075];
bool inq1[17][131075], inq2[17][131075];
int nr[131075];

int main()
{
    ifstream in("ubuntzei.in");
    ofstream out("ubuntzei.out");

    int n, m;
    in >> n >> m;

    int k;
    in >> k;
    friends[0] = 1;
    for (int i = 1; i <= k; i++)
        in >> friends[i];
    friends[k+1] = n;

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

    for (int start = 0; start <= k+1; start++)
    {
        for (int i = 1; i <= n; i++)
            d[start][i] = INF;
        d[start][friends[start]] = 0;
        pq.push(make_pair(0, friends[start]));

        while (!pq.empty())
        {
            int node = pq.top().second;
            pq.pop();
            if (vis[start][node])
                continue;
            vis[start][node] = true;
            for (int i = 0; i < g[node].size(); i++)
                if (d[start][g[node][i]] > d[start][node] + cost[node][i])
                {
                    d[start][g[node][i]] = d[start][node] + cost[node][i];
                    pq.push(make_pair(-d[start][g[node][i]], g[node][i]));
                }
        }
    }

    for (int i = 0; i <= k+1; i++)
    {
        for (int j = 0; j <= k+1; j++)
        {
            df[i][j] = d[i][friends[j]];
            //out << df[i][j] << ' ';
        }
        //out << '\n';
    }

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

    k++;
    int invert = (1<<(k+1))-1;

    if ((k+1)/2 > 1)
        q.push(make_pair(k, 1<<k));
    config2[k][1<<k] = 1;
    nr[1<<k] = 1;
    inq2[k][1<<k] = true;
    while (!q.empty())
    {
        int first = q.front().first;
        int config = q.front().second;
        q.pop();
        for (int i = 1; i < k; i++)
            if (!(config & (1<<i)))
            {
                int nc = config | (1<<i);
                if (config2[i][nc] > config2[first][config] + df[i][first] || config2[i][nc] == 0)
                {
                    config2[i][nc] = config2[first][config] + df[i][first];
                    nr[nc] = nr[config] + 1;
                    if (nr[nc] < (k+1)/2 && !inq2[i][nc])
                    {
                        q.push(make_pair(i, nc));
                        inq2[i][nc] = true;
                    }
                }
            }
    }

    int sol = INF;

    q.push(make_pair(0, 1));
    config1[0][1] = 0;
    nr[1] = 1;
    inq1[0][1] = true;
    while (!q.empty())
    {
        int last = q.front().first;
        int config = q.front().second;
        q.pop();

        for (int i = 1; i < k; i++)
            if (!(config & (1<<i)))
            {
                int nc = config | (1<<i);
                if (config1[i][nc] > config1[last][config] + df[last][i] || config1[i][nc] == 0)
                {
                    config1[i][nc] = config1[last][config] + df[last][i];
                    nr[nc] = nr[config] + 1;
                    if (nr[nc] < k/2+1 && !inq1[i][nc])
                    {
                        q.push(make_pair(i, nc));
                        inq1[i][nc] = true;
                    }
                    else if (nr[nc] == k/2+1)
                    {
                        //out << i << ' ' << nc << '\n';
                        inq1[i][nc] = true;
                        for (int j = 1; j <= k; j++)
                            if (!(nc & (1<<j)))
                            {
                                //out << j << ' ' << (nc ^ invert) << '\n' << config1[i][nc] << ' ' << config2[j][nc ^ invert] - 1 << ' ' << df[i][j] << '\n';
                                if (config2[j][nc ^ invert])
                                    sol = min(sol, config1[i][nc] + config2[j][nc ^ invert] + df[i][j] - 1);
                            }
                        //out << '\n';
                    }
                }
            }
    }

    out << sol << '\n';

    return 0;
}