Cod sursa(job #2975187)

Utilizator Matei_MunteanuMunteanu Matei Ioan Matei_Munteanu Data 5 februarie 2023 18:56:36
Problema Gather Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.6 kb
#include <bits/stdc++.h>
using namespace std;
const int NMAX = 754;
const int KMAX = 15;

ifstream fin("gather.in");
ofstream fout("gather.out");

int n, m, k;
int pers[KMAX + 4];
struct edge
{
    int u;
    int c;
    int p;
};
vector<edge> adj[NMAX];
int dp[KMAX + 4][(1 << KMAX) + 4];
int d[KMAX + 4][KMAX + 4][KMAX + 4];
int d1[NMAX];
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> Q;
int rez = INT_MAX;

void dijkstra(int s, int max_p)
{
    int dist[NMAX];
    for (int i = 1; i <= n; i++)
    {
        dist[i] = INT_MAX;
    }
    dist[pers[s]] = 0;
    Q.push({0, pers[s]});
    while (!Q.empty())
    {
        int v = Q.top().second;
        int d_v = Q.top().first;
        Q.pop();
        if (d_v != dist[v])
        {
            continue;
        }
        for (auto e : adj[v])
        {
            int u = e.u;
            int cost = e.c;
            int p = e.p;
            if (dist[v] + cost < dist[u] && max_p <= p)
            {
                dist[u] = dist[v] + cost;
                Q.push({dist[u], u});
            }
        }
    }
    for (int i = 1; i <= k; i++)
    {
        d[s][i][max_p] = dist[pers[i]];
    }
}

void dijkstra1()
{
    for (int i = 1; i <= n; i++)
    {
        d1[i] = INT_MAX;
    }
    d1[1] = 0;
    Q.push({0, 1});
    while (!Q.empty())
    {
        int v = Q.top().second;
        int d_v = Q.top().first;
        Q.pop();
        if (d_v != d1[v])
        {
            continue;
        }
        for (auto e : adj[v])
        {
            int u = e.u;
            int cost = e.c;
            if (d1[v] + cost < d1[u])
            {
                d1[u] = d1[v] + cost;
                Q.push({d1[u], u});
            }
        }
    }
}

int main()
{
    fin >> k >> n >> m;
    for (int i = 1; i <= k; i++)
    {
        fin >> pers[i];
    }
    for (int i = 1; i <= m; i++)
    {
        int a, b, c, d;
        fin >> a >> b >> c >> d;
        adj[a].push_back({b, c, d});
        adj[b].push_back({a, c, d});
    }
    dijkstra1();
    for (int i = 1; i <= k; i++)
    {
        for (int j = 1; j <= k; j++)
        {
            dijkstra(i, j);
        }
    }
    for (int i = 1; i <= k; i++)
    {
        for (int conf = 0; conf < (1 << k); conf++)
        {
            dp[i][conf] = INT_MAX;
        }
    }
    for (int i = 1; i <= k; i++)
    {
        dp[i][1 << (i - 1)] = d1[pers[i]];
    }
    for (int conf = 1; conf < (1 << k); conf++)
    {
        for (int i = 1; i <= k; i++)
        {
            if (conf & (1 << (i - 1)))
            {
                for (int j = 1; j <= k; j++)
                {
                    if (i == j)
                    {
                        continue;
                    }
                    if (conf & (1 << (j - 1)))
                    {
                        int p = __builtin_popcount(conf);
                        if (d[i][j][p] < INT_MAX)
                        {
                            dp[j][conf] = min(dp[j][conf], dp[i][conf ^ (1 << (j - 1))] + p * d[i][j][p - 1]);
                        }
                    }
                }
            }
        }
    }
    // for (int i = 1; i <= k; i++)
    // {
    //     for (int conf = 1; conf < (1 << k); conf++)
    //     {
    //         cout << conf << ' ' << dp[i][conf] << ' ';
    //     }
    //     cout << '\n';
    // }
    for (int i = 1; i <= k; i++)
    {
        rez = min(rez, dp[i][(1 << k) - 1]);
    }
    fout << rez;
    fin.close();
    fout.close();
    return 0;
}