Cod sursa(job #1743596)

Utilizator fanache99Constantin-Buliga Stefan fanache99 Data 18 august 2016 14:07:00
Problema Gather Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.37 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <limits>
#include <cstring>
#include <queue>
using namespace std;

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

const int MAXN = 750;
const int MAXK = 15;
const long long INFLL = numeric_limits<long long>::max();

int k, n, m;

int which[MAXK], index[1 + MAXN];
long long dp[1 + MAXK][1 << MAXK], step[1 + MAXK][1 + MAXK][1 + MAXK];

struct Edge{
    int node;
    int cost;
    int people;
    Edge(int _node, int _cost, int _people):
        node(_node),
        cost(_cost),
        people(_people) {}
};

vector<Edge> g[1 + MAXN];

int BitCount(int mask) {
    int answer = 0;
    while (mask) {
        mask -= (mask & -mask);
        answer++;
    }
    return answer;
}

bool inQueue[1 + MAXN];
long long best[1 + MAXN];
queue<int> Queue;

void Solve() {
    memset(dp, 0x3f3f3f3f, sizeof(dp));
    for (int people = 0; people <= k; people++)
        for (int start = 1; start <= k + 1; start++)
            if (start != k + 1 || people == 0) {
                memset(inQueue, false, sizeof(inQueue));
                memset(best, 0x3f3f3f3f, sizeof(best));
                if (start == k + 1) {
                    Queue.push(1);
                    inQueue[1] = true;
                    best[1] = 0;
                }
                else {
                    Queue.push(which[start - 1]);
                    inQueue[which[start - 1]] = true;
                    best[which[start - 1]] = 0;
                }
                while (!Queue.empty()) {
                    int node = Queue.front();
                    Queue.pop();
                    inQueue[node] = false;
                    for (auto &edge : g[node])
                        if (edge.people >= people)
                            if (best[edge.node] > best[node] + edge.cost * (people + 1)) {
                                best[edge.node] = best[node] + edge.cost * (people + 1);
                                if (!inQueue[edge.node]) {
                                    Queue.push(edge.node);
                                    inQueue[edge.node] = true;
                                }
                            }
                }
                if (start == k + 1)
                    for (int j = 1; j <= k; j++)
                        dp[j][0] = best[which[j - 1]];
                else
                    for (int j = 1; j <= k; j++)
                        step[people][start][j] = best[which[j - 1]];
            }
    for (int mask = 0; mask < (1 << k); mask++)
        for (int i = 1; i <= k; i++)
            for (int j = 1; j <= k; j++)
                if (!(mask & (1 << (j - 1))))
                    dp[j][mask | (1 << (j - 1))] = min(dp[j][mask | (1 << (j - 1))], dp[i][mask] + step[BitCount(mask)][i][j]);
}

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

    for (int i = 1; i <= n; i++)
        index[i] = -1;

    for (int i = 0; i < k; i++) {
        cin >> which[i];
        index[which[i]] = i;
    }

    for (int i = 1; i <= m; i++) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        g[a].push_back(Edge(b, c, d));
        g[b].push_back(Edge(a, c, d));
    }

    Solve();

    long long answer = INFLL;
    for (int i = 1; i <= k; i++)
        answer = min(answer, dp[i][(1 << k) - 1]);
    cout << answer << "\n";
    return 0;
}