Cod sursa(job #877314)

Utilizator repp4raduRadu-Andrei Szasz repp4radu Data 12 februarie 2013 19:25:44
Problema Gather Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.9 kb
#include <fstream>
#include <vector>
#include <queue>
#include <cstring>

#define NMAX 755
#define MMAX 1255
#define KMAX 17
#define INF (1LL << 60)
#define pb push_back

using namespace std;

int N, M, K, ind, C;
long long S[KMAX], A[(1 << KMAX)];
long long dp[(1 << KMAX)][NMAX];
//dist[i][j][k] - cea mai mica distanta pornind de la nodul S[j] pana la nodul i,
                //utilizand muchii de capacitate >= k
long long dist[NMAX][KMAX][KMAX];
bool inQueue[NMAX];

struct MUCHIE
{
    int X, Y, D, C;
} G[MMAX];

vector<int> V[NMAX];

struct CMP
{
    bool operator() (const int &X, const int &Y)
    {
        return dist[X][ind][C] > dist[Y][ind][C];
    }
};

priority_queue<int, vector<int>, CMP> Q;

void dijkstra(int poz, int nod, int cap)
{
    ind = poz; C = cap;
    for(int i = 0; i <= N; i++) dist[i][poz][cap] = INF;
    memset(inQueue, 0, sizeof(inQueue));
    dist[nod][poz][cap] = 0;
    Q.push(nod);
    while(!Q.empty())
    {
        int nod = Q.top(); Q.pop();
        for(size_t i = 0; i < V[nod].size(); i++)
        {
            if(G[V[nod][i]].D < cap) continue;
            int neighbour = G[V[nod][i]].X + G[V[nod][i]].Y - nod;
            if(dist[nod][poz][cap] + G[V[nod][i]].C < dist[neighbour][poz][cap])
            {
                dist[neighbour][poz][cap] = dist[nod][poz][cap] + G[V[nod][i]].C;
                if(!inQueue[neighbour])
                {
                    inQueue[neighbour] = true;
                    Q.push(neighbour);
                }
            }
        }
    }
}

int main()
{
    ifstream in("gather.in");
    in>>K>>N>>M;
    for(int i = 0; i < K; i++) in>>S[i];
    for(int i = 1; i <= M; i++)
    {
        in>>G[i].X>>G[i].Y>>G[i].C>>G[i].D;
        V[G[i].X].pb(i);
        V[G[i].Y].pb(i);
    } in.close();
    for(int i = 0; i <= K; i++) dijkstra(K, 1, i);
    for(int i = 0; i < K; i++)
        for(int j = 0; j <= K; j++)
            dijkstra(i, S[i], j);
    for(int conf = 1; conf < (1 << K); conf++)
        A[conf] = A[conf & (conf - 1)] + 1;
    for(int conf = 1; conf < (1 << K); conf++)
        if(!(conf & (conf - 1)))
        {
            int i;
            for(i = 0; !((1 << i) & conf); i++);
            dp[conf][i] = dist[S[i]][K][0];
            i = 5;
        }
        else
            for(int i = 0; i < K; i++)
            {
                dp[conf][i] = INF;
                if(conf & (1 << i))
                    for(int j = 0; j < K; j++)
                        if(i != j && (conf & (1 << j)))
                            dp[conf][i] = min(dp[conf][i], dp[conf ^ (1 << i)][j] +
                                              dist[S[i]][j][A[conf] - 1] * (A[conf]));
            }
    long long minim = INF;
    for(int i = 0; i < K; i++) minim = min(minim, dp[(1 << K) - 1][i]);
    ofstream out("gather.out"); out<<minim<<"\n"; out.close();
    return 0;
}