Cod sursa(job #2184253)

Utilizator andreicoman299Coman Andrei andreicoman299 Data 23 martie 2018 21:17:20
Problema Gather Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.61 kb
#include <bits/stdc++.h>
#define MAXN 1000
#define MAXK 16

const long long INF = 1000000000000000LL;
struct Edge{long long dest; long long cost, cap;};
std::vector <long long> V;
std::vector <Edge> G[1 + MAXN];

long long d[1 + MAXK][1 + MAXK][1 + MAXN];
long long inq[1 + MAXN];
std::queue <long long> q;

long long dp[1 << MAXK][1 + MAXK];
int main(){
    FILE*fi,*fo;
    fi = fopen("gather.in","r");
    fo = fopen("gather.out","w");

    long long n, k, m, x;
    fscanf(fi,"%lld%lld%lld", &k, &n, &m);
    for(long long i = 1; i <= k; i++) fscanf(fi,"%lld", &x), V.push_back(x);
    for(long long i = 1; i <= m; i++){
        long long a, b;
        long long c, d;
        fscanf(fi,"%lld%lld%lld%lld", &a, &b, &c, &d);
        G[a].push_back({b, c, d});
        G[b].push_back({a, c, d});
    }

    for(long long D = 0; D < k; D++){
        for(long long i = 1; i <= n; i++)
            for(long long j = 0; j < G[i].size(); j++)
                if(G[i][j].cap < 1LL * D) std::swap(G[i][j], G[i][G[i].size() - 1]), G[i].pop_back();
        for(long long ind = 0; ind < V.size(); ind++){
            long long S = V[ind];
            for(long long i = 1; i <= n; i++) d[D][ind][i] = INF;
            q.push(S); d[D][ind][S] = 0LL; inq[S] = 1;
            while(!q.empty()){
                long long node = q.front(); q.pop(); inq[node] = 0;
                for(auto y: G[node]) if(d[D][ind][node] + y.cost < d[D][ind][y.dest]){
                    d[D][ind][y.dest] = d[D][ind][node] + y.cost;
                    if(!inq[y.dest]) inq[y.dest] = 1, q.push(y.dest);
                }
            }
        }
    }

    for(long long mask = 1; mask < (1 << k); mask++)
        if(__builtin_popcount(mask) == 1)
            for(long long i = 0; i < k; i++){
                dp[mask][i] = INF;
                if((mask & (1 << i)) && d[0][i][1] != INF) dp[mask][i] = std::min(dp[mask][i], d[0][i][1]);
            }
        else{
            long long cnt = __builtin_popcount(mask) - 1;
            for(long long i = 0; i < k; i++){
                dp[mask][i] = INF;
                for(long long j = 0; j < k; j++)
                    if(i != j && (mask & (1 << i)) && (mask & (1 << j)) && dp[mask ^ (1 << i)][j] != INF && d[cnt][j][V[i]] != INF)
                        dp[mask][i] = std::min(dp[mask][i], dp[mask ^ (1 << i)][j] + 1LL * (cnt + 1) * d[cnt][j][V[i]]);
            }
        }

    long long min = INF;
    for(long long i = 0; i < k; i++) if(dp[(1 << k) - 1][i] < min) min = dp[(1 << k) - 1][i];
    if(min > (1LL << 32)) while(1){};
    fprintf(fo,"%lld", min);

    return 0;
}