Cod sursa(job #1122056)

Utilizator alexclpAlexandru Clapa alexclp Data 25 februarie 2014 15:45:21
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.41 kb
#include <fstream>
#include <vector>
#include <queue>
#include <climits>

using namespace std;

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

const int N = 10005;
const int INF = 200000000;
const int K = 20;

struct Muchie {
    int nod;
    int cost;
};

int noduri, muchii;
int nodAdaugat;

int numarTreceri[N];
int cost[N];

int graf2[K][K];
int d[131072][K];

vector <int> deVizitat;
vector <Muchie> a[N];

Muchie getMuchie(int a, int b)
{
    Muchie m;
    m.nod = a;
    m.cost = b;
    return m;
}

int minim (int a, int b)
{
    return a < b ? a : b;
}

void read()
{
    in >> noduri >> muchii;

    int k;
    in >> k;

    for (int i = 1; i <= k; i++) {
        int x;
        in >> x;
        deVizitat.push_back(x);
    }

    for (int i = 1; i <= muchii; i++) {
        int x, y, z;

        in >> x >> y >> z;
        a[x].push_back(getMuchie(y, z));
        a[y].push_back(getMuchie(x, z));
    }
}

void initializeaza()
{
    for (int i = 1; i <= noduri; ++i) {
        numarTreceri[i] = 0;
        cost[i] = INF;
    }
}

void cicluHamilton()
{
    int numarVarfuri = deVizitat.size() + 2;
    for (int i = 1; i < numarVarfuri; ++i) {
        d[1][i] = INF;
    }

    int numarPermutari = (1 << numarVarfuri) - 1;
    for (int i = 3; i <= numarPermutari; i += 2) {
        d[i][0] = INF;
        for (int j = 1; j < numarVarfuri; ++j) {
            d[i][j] = INF;
            int j2 = (1 << j);
            if (i & j2) {
                int iprim = i ^ j2;
                for (int k = 0; k < numarVarfuri; ++k) {
                    int k2 = (1 << k);
                    if (graf2[k][j] != 0 and (iprim & k2) and (j != k)) {
                        d[i][j] = minim (d[i][j], d[iprim][k] + graf2[k][j]);
                    }
                }
            }
        }
    }

    int sol = INF;
    for (int i = 1; i <= numarVarfuri; ++i) {
        if (graf2[i][0] != 0) {
            sol = minim (sol, d[numarPermutari][i] + graf2[i][numarVarfuri-1]);
        }
    }
    out << sol << "\n";
}

void bfd(int nod)
{
    queue <int> coada;

    initializeaza();
    cost[nod] = 0;

    coada.push(nod);
    while(!coada.empty()) {
        int nodVechi = coada.front();
        int costVechi = cost[nodVechi];
        coada.pop();

        for (int i = 0; i < a[nodVechi].size(); ++i) {
            int nodNou = a[nodVechi][i].nod;
            int costNou = a[nodVechi][i].cost;

            if (cost[nodNou] > costNou + costVechi) {
                numarTreceri[nodNou]++;
                if (numarTreceri[nodNou] >= noduri) {
                    return;
                }
                coada.push(nodNou);
                cost[nodNou] = costNou + costVechi;
            }
        }
    }

    // construiesc noul graf

    if (nod != 1) {
        graf2[nodAdaugat][0] = cost[1];
    }

    for (int i = 0; i < deVizitat.size(); ++i) {
        if (deVizitat[i] != nod) {
            graf2[nodAdaugat][i+1] = cost[deVizitat[i]];
        }
    }

    if (nod != noduri) {
        graf2[nodAdaugat][deVizitat.size()+1] = cost[noduri];
    }

    nodAdaugat++;
}

void solve()
{
    bfd(1);
    for (int index = 0; index < deVizitat.size(); ++index) {
        bfd(deVizitat[index]);
    }
    bfd(noduri);
    cicluHamilton();
}

int main()
{
    read();
    solve();

    return 0;
}