Cod sursa(job #1725593)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 5 iulie 2016 23:41:54
Problema Team Scor 15
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.02 kb
#include <fstream>
#include <cstring>
#include <cassert>

using namespace std;

constexpr int MAX_N = 500;
constexpr int MAX_P = 50;
constexpr int MAX_M = 100001;
constexpr int INF = 0x3f3f3f3f;
constexpr int NIL = -1;

struct Edge {
    int v, cost;
    int next;
} G[2 * MAX_M];

int head[MAX_N];

void addEdge(const int u,
             const int v,
             const int weight,
             const int pos) {
    G[pos].v = v;
    G[pos].cost = weight;
    G[pos].next = head[u];
    head[u] = pos;
}

int residence[MAX_P + 1];
int dp[MAX_P][MAX_P][MAX_P + 1];

int pathWeight[MAX_P + 1][MAX_N];
int heap[MAX_N];
int heapPos[MAX_N];

void downHeap(int node,
              const int heapSize,
              const int foo[]) {
    int best; bool changed;
    do {
        changed = false;
        best = node;
        #define W(x) if ((x) < heapSize and foo[heap[(x)]] < foo[heap[best]]) best = (x);
        W(node + node + 1) W(node + node + 2)
        if (best != node) {
            changed = true;
            heapPos[best] = node;
            heapPos[node] = best;
            swap(heap[best], heap[node]);
            node = best;
        }
    } while (changed);
}

void upHeap(int node,
            const int foo[]) {
    int parent = (node - 1) >> 1;
    while (node and foo[heap[parent]] > foo[heap[node]]) {
        heapPos[heap[parent]] = node;
        heapPos[heap[node]] = parent;
        swap(heap[parent], heap[node]);
        node = parent;
        parent = (node - 1) >> 1;
    }
}

void Dijkstra(const int node,
              const int n,
              int weight[]) {
    for (int i = 0; i < n; i += 1) {
        weight[i] = INF;
        heap[i] = i;
        heapPos[i] = i;
    }
    weight[node] = 0;
    heapPos[0] = node; heapPos[node] = 0;
    heap[0] = node; heap[node] = 0;
    for (int i = n - 1; i >= 0; i -= 1) {
        const int node = heap[0];
        heap[0] = heap[i];
        downHeap(0, i, weight);
        for (int j = head[node]; j != NIL; j = G[j].next) {
            const int son = G[j].v;
            if (weight[son] > weight[node] + G[j].cost) {
                weight[son] = weight[node] + G[j].cost;
                upHeap(heapPos[son], weight);
            }
        }
    }
}

int main() {
    ifstream fin("team.in");
    ofstream fout("team.out");
    fin.tie(0);
    ios_base::sync_with_stdio(false);
    int p, n, e; fin >> p >> n >> e;
    memset(head, NIL, 4 * n);
    for (int i = 0; i < e; i += 1) {
        int node_1, node_2, weight; fin >> node_1 >> node_2 >> weight;
        addEdge(node_1 - 1,
                node_2 - 1,
                weight,
                2 * i);
        addEdge(node_2 - 1,
                node_1 - 1,
                weight,
                2 * i + 1);
    }
    for (int i = 0; i <= p; i += 1) {
        if (i) {
            fin >> residence[i]; residence[i] -= 1;
        }
        Dijkstra(residence[i],
                 n,
                 pathWeight[i]);
    }
    for (int i = 0; i < p; i += 1) {
        for (int k = 0; k <= p; k += 1) {
            dp[i][i][k] = pathWeight[i + 1][residence[k]];
        }
        for (int j = i + 1; j < p; j += 1) {
            for (int k = 0; k <= p; k += 1) {
                dp[i][j][k] = INF;
            }
        }
    }
    for (int st = p - 2; st >= 0; st -= 1) {
        for (int dr = st + 1; dr < p; dr += 1) {
            for (int node = 0; node <= p; node += 1) {
                int x = INF;
                for (int split = st; split <= dr; split += 1) {
                    const int option = dp[st][split - 1][split + 1]
                                    + pathWeight[node][residence[split + 1]]
                                    + dp[split + 1][dr][split + 1];
                    if (option < x) {
                        x = option;
                    }
                }
                dp[st][dr][node] = x;
            }
        }
    }
    fout << dp[0][p - 1][0] << '\n';
    fout.close();
    return 0;
}