Cod sursa(job #1154107)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 25 martie 2014 23:01:17
Problema Team Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.26 kb
#include <cstdio>
#include <cstring>
#include <cassert>

#include <vector>
#include <algorithm>

using namespace std;

const int oo = 0x3f3f3f3f;
const int NIL = -1;
const int MAX_V = 500;
const int MAX_N = 50;

class Reader {
  public:
    Reader(FILE *_stream, const int _size = (1 << 16)):
      size(_size),
      pointer(0),
      buffer(new char[_size]),
      stream(_stream) {
        assert(fread(buffer, 1, size, stream) != 0);
    }

    template<class IntType>
    IntType NextInt() {
        IntType value = 0;
        bool negative = false;
        while ((Current() < '0' || Current() > '9') && Current() != '-')
            NextPosition();
        if (Current() == '-') {
            negative = true;
            NextPosition();
        }
        while(Current() >= '0' && Current() <= '9') {
            value = value * 10 + Current() - '0';
            NextPosition();
        }
        if (negative)
            value = -value;
        return value;
    }

    Reader &operator>>(int &value) {
        value = NextInt<int>();
        return *this;
    }

  private:
    int size, pointer;
    char *buffer;
    FILE *stream;

    char Current() const {
        return buffer[pointer];
    }

    void NextPosition() {
        if(++pointer == size) {
            assert(fread(buffer, 1, size, stream) != 0);
            pointer = 0;
        }
    }
};

int N, V, G[MAX_V][MAX_V], Source, Answer;
int Destinations[MAX_N], Cost[MAX_N + 1][MAX_N + 1];

void Dijkstra(const int source, int distances[MAX_V]) {
    bool used[MAX_V];
    memset(used, 0, sizeof(used));
    for (int x = 0; x < V; ++x)
        distances[x] = oo;
    distances[source] = 0;
    int x = source;
    do {
        for (int y = 0; y < V; ++y)
            if (!used[y])
                distances[y] = min(distances[y], distances[x] + G[x][y]);
        used[x] = true;
        x = NIL;
        for (int y = 0; y < V; ++y)
            if (!used[y] && (x == NIL || distances[y] < distances[x]))
                x = y;
    } while (x != NIL);
}

void BuildCost() {
    vector<int> vertices;
    vertices.push_back(Source);
    for (int x = 0; x < N; ++x)
        vertices.push_back(Destinations[x]);
    sort(vertices.begin(), vertices.end());
    vertices.erase(unique(vertices.begin(), vertices.end()), vertices.end());
    int newV = int(vertices.size()), newIndex[MAX_V];
    memset(newIndex, -1, sizeof(newIndex));
    for (int i = 0; i < newV; ++i)
        newIndex[vertices[i]] = i;
    for (int x = 0; x < N; ++x)
        Destinations[x] = newIndex[Destinations[x]];
    for (int i = 0; i < newV; ++i) {
        int distances[MAX_V];
        Dijkstra(vertices[i], distances);
        for (int j = 0; j < newV; ++j)
            Cost[i][j] = distances[vertices[j]];
    }
    V = newV;
}

void Solve() {
    BuildCost();
    int dp[MAX_N + 1][MAX_N][MAX_N];
    memset(dp, oo, sizeof(dp));
    for (int length = 1; length <= N; ++length) {
        for (int x = 0; x < V; ++x) {
            for (int first = 0, last = length - 1; last < N; ++first, ++last) {
                for (int split = first; split <= last; ++split) {
                    int current = Cost[x][Destinations[split]];
                    if (split > first)
                        current += dp[Destinations[split]][first][split - 1];
                    if (split < last)
                        current += dp[Destinations[split]][split + 1][last];
                    dp[x][first][last] = min(dp[x][first][last], current);
                }
            }
        }
    }
    Answer = dp[Source][0][N - 1];
}

void Read() {
    assert(freopen("team.in", "r", stdin));
    Reader in = Reader(stdin);
    int E;
    in >> N >> V >> E;
    memset(G, oo, sizeof(G));
    for (int x = 0; x < V; ++x)
        G[x][x] = 0;
    for (; E > 0; --E) {
        int x, y, c;
        in >> x >> y >> c;
        --x;
        --y;
        G[x][y] = G[y][x] = c;
    }
    for (int x = 0; x < N; ++x) {
        in >> Destinations[x];
        --Destinations[x];
    }
    Source = 0;
    fclose(stdin);
}

void Print() {
    assert(freopen("team.out", "w", stdout));
    printf("%d\n", Answer);
    fclose(stdout);
}

int main() {
    Read();
    Solve();
    Print();
    return 0;
}