Cod sursa(job #115883)

Utilizator filipbFilip Cristian Buruiana filipb Data 17 decembrie 2007 12:26:32
Problema Gather Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.71 kb
#include <stdio.h>
#include <vector>
#include <set>

using namespace std;

#define minim(a, b) ((a < b) ? a : b)
#define INF 2000000001
#define PII pair<int, int>
#define mp make_pair
#define pb push_back
#define nod first.first
#define cost first.second
#define cap second
#define NMax 755

int K, N, M, nodes[16], biti[1<<15], d[NMax];
int dist[16][16][16], opt[1<<15][16], bst = INF;
vector< pair< PII, int > > G[NMax];
set<PII> HEAP;

int bit(int X, int nr_bit)
{ return (X & (1<<nr_bit)) != 0; }

void Djikstra(int cap_min, int sursa, int indice)
{
    int i, j, sz, nd, x, cst;
    set<PII>::iterator hd;

    HEAP.clear();
    for (i = 1; i <= N; i++)
        d[i] = INF * (i != sursa),
        HEAP.insert( mp(d[i], i) );

    for (i = 1; i < N; i++)
    {
        hd = HEAP.begin();
        HEAP.erase(hd);        
        nd = hd->second;

        for (sz = G[nd].size(), j = 0; j < sz; j++)
            if (G[nd][j].cap >= cap_min)
            {
                x = G[nd][j].nod;
                cst = G[nd][j].cost;
                if (d[nd] + cst < d[x])
                {
                    HEAP.erase( HEAP.find( mp(d[x], x) ) );
                    d[x] = d[nd] + cst;
                    HEAP.insert( mp(d[x], x) );
                }
            }
    }
    
    for (i = 0; i <= K; i++)
        dist[cap_min][indice][i] = d[nodes[i]];
}
          
int main(void)
{
    int i, j, k, p, c, d, c_old;
    
    freopen("gather.in", "r", stdin);
    freopen("gather.out", "w", stdout);

    scanf("%d %d %d", &K, &N, &M);
    for (i = 1, nodes[0] = 1; i <= K; i++)
        scanf("%d", &nodes[i]);
    for (i = 1; i < (1<<K)*4; i++)
        biti[i] = biti[i/2] + (i % 2);
        
    for (; M; M--)
    {
        scanf("%d %d %d %d", &i, &j, &c, &d);
        G[i].pb( mp( mp(j, c), d ) );
        G[j].pb( mp( mp(i, c), d ) );
    }

    for (i = 0; i <= K; i++)
        for (j = 0; j <= K; j++)
            Djikstra(i, nodes[j], j);

    for (i = 0; i < (1<<K); i++)
        for (j = 0; j <= K; j++)
            opt[i][j] = INF;            

    for (k = 1; k <= K; k++)
        opt[1<<(k-1)][k] = dist[0][0][k];
    
    for (c = 1; c < (1<<K); c++)
        for (k = 1; k <= K; k++)
            if (opt[c][k] == INF && bit(c, k-1))
            {
                c_old = c - (1<<(k-1));
                for (p = 1; p <= K; p++)
                    if (opt[c_old][p] < INF && dist[biti[c_old]][p][k] < INF)
                        opt[c][k] = minim(opt[c][k], opt[c_old][p] + dist[biti[c_old]][p][k] * (biti[c_old]+1));
            }

    for (i = 1; i <= K; i++)
        bst = minim(bst, opt[(1<<K)-1][i]);
    printf("%d\n", bst);

    return 0;
}