Cod sursa(job #1853669)

Utilizator TimitocArdelean Andrei Timotei Timitoc Data 21 ianuarie 2017 22:20:16
Problema Gather Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.58 kb
/// 21 Ianuarie, mintea imi joaca feste
#include <iostream>
#include <cstdio>
#include <queue>
#include <vector>
#define MAXN 760
#define MAXK 16
#define inf 1LL<<55LL

using namespace std;

long long dk[MAXK], best[MAXN], cost[MAXN][MAXN], cap[MAXN][MAXN];
long long dist[MAXK][MAXK][MAXK];
long long n, k, m;
vector<int> graf[MAXN];
struct cmp
{
    bool operator()(const int &x, const int &y)
    {
        return best[x] > best[y];
    }
};
priority_queue<int, vector<int>, cmp> heap;

void dijkstra(int src, int capmin)
{
    for (int i = 0; i <= n; i++)
        best[i] = inf;
    best[dk[src]] = 0;
    while (!heap.empty()) heap.pop();
    heap.push(dk[src]);
    while (!heap.empty())
    {
        int nod = heap.top();
        heap.pop();
        for (int y : graf[nod])
            if (cap[nod][y] >= capmin && best[nod] + cost[nod][y] < best[y])
            {
                best[y] = best[nod] + cost[nod][y];
                heap.push(y);
            }
    }
    for (int i = 0; i <= k; i++)
        dist[capmin][src][i] = best[dk[i]];
}

long long din[1<<MAXK][MAXK]; /// dist min pentru a ajunge la nodul j cu prizionierii i

int cati(int nr)
{
    int rez = 0;
    while (nr)
    {
        rez += nr & 1;
        nr >>= 1;
    }
    return rez;
}

void solve()
{
    for (int i = 0; i < (1<<k); i++)
        for (int j = 0; j <= k; j++)
            din[i][j] = inf;
    din[0][k] = 0;
    for (int i = 0; i < (1<<k); i++)
    {
        for (int j = 0; j < k; j++)
        {
            if (!(i & (1 << j))) continue;
            for (int v = 0; v <= k; v++)
                if (j!= v)
                {
                    int c = cati(i^(1<<j));
                    din[i][j] = min(din[i][j], din[i^(1<<j)][v] + 1LL*dist[c][v][j] * (c+1));
                }
        }
    }
    long long sol = inf;
    for (int i = 0; i < k; i++)
        sol = min(sol, din[(1<<k)-1][i]);
    printf("%lld", sol);
}

int main()
{
    freopen("gather.in", "r", stdin);
    freopen("gather.out", "w", stdout);

    scanf("%d %d %d", &k, &n, &m);
    for (int i = 0; i < k; i++) {
        scanf("%d", &dk[i]);
        //cdk[dk[i]] = i;
    }
    for (int i = 1; i <= m; i++) {
        int a, b, c, d;
        scanf("%d %d %d %d", &a, &b, &c, &d);
        graf[a].push_back(b);
        graf[b].push_back(a);
        cost[a][b] = cost[b][a] = c;
        cap[a][b] = cap[b][a] = d;
    }
    dk[k] = 1;
    for (int i = 0; i <= k; i++)
        for (int j = 0; j <= k; j++)
            dijkstra(i, j);
    solve();

    return 0;
}