Cod sursa(job #2126997)

Utilizator Mihai_PredaPreda Mihai Dragos Mihai_Preda Data 10 februarie 2018 11:11:58
Problema Ubuntzei Scor 35
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.13 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>

using namespace std;

const int INF = 50000000;

struct prieten
{
    int id;
    int distStart, distStop;
    vector<int> dist; //dist[i] = distanta pana la prietenul i
};

void GetDist(vector<int> &ret, vector<vector<pair<int, int> > > &vecini, int start)
{
    fill(ret.begin(), ret.end(), INF);
    priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;
    q.push(make_pair(0, start));
    vector<bool> viz(ret.size(), false);
    pair<int, int> p;
    ret[start] = 0;
    while(q.empty() == false)
    {
        p = q.top();
        q.pop();
        if(viz[p.second])
            continue;
        viz[p.second] = true;
        for(auto v:vecini[p.second])
            if(ret[v.second] > p.first + v.first)
            {
                ret[v.second] = p.first + v.first;
                q.push(make_pair(ret[v.second], v.second));
            }

    }
}

int main()
{
    ifstream in("ubuntzei.in");
    int n, m, k;
    in >> n >> m;
    in >> k;
    vector<prieten> prieteni(k);
    for(int i = 0; i < k; ++i)
        in >> prieteni[i].id;
    vector<vector<pair<int, int> > > vecini(n + 1); //.first = cost, .second = vecin
    int x, y, z;
    while(m--)
    {
        in >> x >> y >> z;
        vecini[x].push_back(make_pair(z, y));
        vecini[y].push_back(make_pair(z, x));
    }
    in.close();
    vector<int> dist(n + 1);
    for(auto &p:prieteni)
    {
        p.dist.resize(prieteni.size());
        GetDist(dist, vecini, p.id);
        p.distStart = dist[1];
        p.distStop = dist[n];
        for(int i = 0; i < prieteni.size(); ++i)
            p.dist[i] = dist[prieteni[i].id];
    }
    int rasp;
    if(prieteni.size() == 0)
    {
        GetDist(dist, vecini, 1);
        rasp = dist[n];
    }
    else if(prieteni.size() == 1)
        rasp = prieteni[0].distStart + prieteni[0].distStop;
    else
    {
        rasp = INF;
        int i = 0;
        vector<vector<int> > dp(1 << (prieteni.size() + 1), vector<int>(prieteni.size(), INF));
        dp[1 << i][i] = 0;
        for(int j = 0; j < (1 << prieteni.size()); ++j)
        {
            if((j & (1 << i)) == 0)
                continue;
            for(int k = 0; k < prieteni.size(); ++k)
            {
                if((j & (1 << k)) == 0)
                    continue;
                for(int t = 0; t < prieteni.size(); ++t)
                {
                    if((j & (1 << t)) == 0)
                        continue;
                    dp[j][k] = min(dp[j][k], dp[j - (1 << k)][t] + prieteni[k].dist[t]);
                }
            }
        }
        for(int j = 0; j < prieteni.size(); ++j)
        {
            if(j == i)
                continue;
            int all = (1 << prieteni.size()) - 1 - (1 << j);
            for(int t = 0; t < prieteni.size(); ++t)
                rasp = min(rasp, prieteni[i].distStart + dp[all][t] + prieteni[j].dist[t] + prieteni[j].distStop);
        }
    }
    ofstream out("ubuntzei.out");
    out << rasp;
    out.close();
    return 0;
}