Cod sursa(job #1518234)

Utilizator lacraruraduRadu Matei Lacraru lacraruradu Data 5 noiembrie 2015 19:22:31
Problema Gather Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.68 kb
#include <fstream>

using namespace std;

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

#define N 755
#define K 20
#define M 1255
#define INF (1 << 31) - 1

int n, m, k;
int lst[N], vf[2 * M], urm[2 * M], cost[2 * M], capacitate[2 * M], nr;

int h[N], poz[N], nh;
int d[N], b[K];

int cost2[K][K][K];
int a[1 << K][K];
int biti[1 << K];

void schimba(int i1, int i2)
{
    int aux = h[i1];
    h[i1] = h[i2];
    h[i2] = aux;
    poz[h[i1]] = i1;
    poz[h[i2]] = i2;
}

void urca(int i)
{
    while(i >= 2 && d[h[i]] < d[h[i / 2]])
    {
        schimba(i, i / 2);
        i /= 2;
    }
}

void coboara(int i)
{
    int bun = i, fs = 2 * i, fd = 2 * i + 1;
    if(fs <= nh && d[h[fs]] < d[h[bun]])
        bun = fs;
    if(fd <= nh && d[h[fd]] < d[h[bun]])
        bun = fd;
    if(bun != i)
    {
        schimba(i, bun);
        coboara(bun);
    }
}

void adauga(int x)
{
    h[++nh] = x;
    poz[x] = nh;
    urca(nh);
}

void sterge(int i)
{
    poz[h[i]] = 0;
    schimba(i, nh);
    nh--;
    coboara(i);
}

void dijkstra(int x, int cap)
{
    for(int i = 1; i <= n; i++)
    {
        d[i] = INF;
        h[i] = 0;
        poz[i] = 0;
    }
    nh = 0;

    d[x] = 0;
    adauga(x);
    while(nh)
    {
        x = h[1];
        sterge(1);

        for(int i = lst[x]; i; i = urm[i])
        {
            if(capacitate[i] < cap)
                continue;
            int y, c;
            y = vf[i];
            c = cost[i];

            if(d[x] + c < d[y])
            {
                d[y] = d[x] + c;
                if(poz[y] == 0)
                    adauga(y);
                else
                    urca(poz[y]);
            }
        }
    }
}

int minim(int x, int y)
{
    return x < y ? x : y;
}

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

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

    for(int i = 1; i <= m; i++)
    {
        int x, y, c, cap;
        in >> x >> y >> c >> cap;
        vf[++nr] = y;
        cost[nr] = c;
        capacitate[nr] = cap;
        urm[nr] = lst[x];
        lst[x] = nr;
        vf[++nr] = x;
        cost[nr] = c;
        capacitate[nr] = cap;
        urm[nr] = lst[y];
        lst[y] = nr;
    }

    for(int i = 0; i < k; i++)
        for(int j = 0; j < k; j++)
        {
            dijkstra(b[i], j);
            for(int p = 0; p < k; p++)
            {
                cost2[i][p][j] = INF;
                if(b[i] != b[p] && d[b[p]] != INF)
                    cost2[i][p][j] = d[b[p]];
            }
        }

    for(int i = 1; i <= (1 << k) - 1; i += 2)
    {
        int aux = i;
        int nrb = 0;
        while(aux)
        {
            nrb++;
            aux &= aux - 1;
        }
        biti[i] = nrb;
    }

    for(int i = 1; i <= (1 << k) - 1; i += 2)
        for(int j = 0; j < k; j++)
            a[i][j] = INF;
    a[1][0] = 0;

    for(int i = 3; i <= (1 << k) - 1; i += 2)
        for(int j = 1; j < k; j++)
        {
            if(!(i & (1 << j)))
                continue;
            for(int l = 0; l < k; l++)
                if((i - (1 << j)) & (1 << l) && a[i - (1 << j)][l] != INF)
                {
                    int capmin = biti[i] - 2;
                    for(int cap = capmin; cap < k; cap++)
                        if(cost2[l][j][cap] != INF)
                            a[i][j] = minim(a[i][j], a[i - (1 << j)][l] + cost2[l][j][cap] * (biti[i] - 1));
                }
        }

    int rezminim = INF;
    for(int i = 0; i < k; i++)
        rezminim = minim(rezminim, a[(1 << k) - 1][i]);
    out << rezminim << '\n';

    return 0;
}