Cod sursa(job #1871573)

Utilizator andrei.arnautuAndi Arnautu andrei.arnautu Data 7 februarie 2017 15:18:22
Problema Team Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.04 kb
/**
  *  Worg
  */
#include <queue>
#include <cstdio>
#include <vector>
#include <algorithm>

using std::vector;
using std::priority_queue;

FILE *fin = freopen("team.in", "r", stdin);
FILE *fout = freopen("team.out", "w", stdout);

const int MAX_P = 1 + 50;
const int MAX_N = 1 + 500;
const int MAX_INF = 1000000000;

/*------- Structures --------*/
struct Edge {
    int vertex, cost;
    Edge() {}
    Edge(const int _vertex, const int _cost) {vertex = _vertex; cost = _cost;}

    bool operator <(const Edge &other) const {
        return this->cost > other.cost;
    }
};
/*------- Input data --------*/
int P, N, M;
vector< Edge > graph[MAX_N];
int finish[MAX_P];
/*------- Algorithm data --------*/
int min_dist[MAX_N][MAX_N];
priority_queue< Edge > heap;

int dp[MAX_P][MAX_P][MAX_N];
/*------- --------*/

void ReadInput() {
    scanf("%d%d%d", &P, &N, &M);
    for(int i = 1; i <= M; i++) {
        int u, v, c; scanf("%d%d%d", &u, &v, &c);
        graph[u].push_back(Edge(v, c));
        graph[v].push_back(Edge(u, c));
    }
    for(int i = 1; i <= P; i++) {
        scanf("%d", &finish[i]);
    }
}

void Initialize() {
    for(int i = 1; i <= N; i++) {
        for(int j = 1; j <= N; j++) {
            min_dist[i][j] = MAX_INF;
        }
    }

    for(int i = 1; i <= P; i++) {
        for(int j = 1; j <= P; j++) {
            for(int k = 1; k <= N; k++) {
                dp[i][j][k] = MAX_INF;
            }
        }
    }

    for(int i = 1; i <= P; i++) {
        dp[i][i][finish[i]] = 0;
    }
}

void RunDijkstra(int source) {
    heap.push(Edge(source, 0));
    while(!heap.empty()) {
        int node = heap.top().vertex, cost = heap.top().cost;
        heap.pop();

        if(min_dist[source][node] == MAX_INF) {
            min_dist[source][node] = cost;
            for(Edge edge : graph[node]) {
                if(min_dist[source][edge.vertex] > cost + edge.cost) {
                    min_dist[source][edge.vertex] = cost + edge.cost;
                    heap.push(Edge(edge.vertex, cost + edge.cost));
                }
            }
        }
    }
}

void GetDistances() {
    RunDijkstra(1);  //  Rulam Dijsktra cu pornire din locul unde se afla discoteca
    for(int i = 1; i <= P; i++) {
        RunDijkstra(finish[i]);
    }
}

int GetSolution(int left, int right, int node) {  //  Costul minim pentru a duce persoanele din [{st}, {dr}] acasa, pornind din {node}
    if(left > right) {
        return 0;
    } else if(dp[left][right][node] != MAX_INF) {
        return dp[left][right][node];
    } else {
        for(int x = left; x <= right; x++) {
            dp[left][right][node] = std::min(dp[left][right][node],
                                             GetSolution(left, x - 1, finish[x]) + GetSolution(x + 1, right, finish[x]) + min_dist[node][finish[x]]);
        }
        return dp[left][right][node];
    }
}

int main() {
    ReadInput();
    Initialize();
    GetDistances();
    printf("%d\n", GetSolution(1, P, 1));
    return 0;
}