Cod sursa(job #1003794)

Utilizator poptibiPop Tiberiu poptibi Data 1 octombrie 2013 16:29:32
Problema Gather Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.04 kb
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

const int NMAX = 755, INF = 0x3f3f3f3f, CONFMAX = (1 << 16), KMAX = 16;

int N, M, K, A, B, C, D, Special[KMAX], Min[NMAX][NMAX], Dist[KMAX][NMAX], Dp[CONFMAX][KMAX], Bit[CONFMAX];
vector<pair<int, int> > G[NMAX], GC[NMAX];
bool InQueue[NMAX];

void GetMin(int StartNode, int V[NMAX])
{
    V[StartNode] = INF;
    queue<int> Q;
    Q.push(StartNode);
    
    while(!Q.empty())
    {
        int Node = Q.front(); 
        Q.pop();
        InQueue[Node] = 0;
        
        for(vector<pair<int, int> > :: iterator it = G[Node].begin(); it != G[Node].end(); ++ it)
            if(min(V[Node], it -> second) > V[it -> first])
            {
                V[it -> first] = min(V[Node], it -> second);
                if(!InQueue[it -> first])
                    Q.push(it -> first), InQueue[it -> first] = 1;
            }
    }
}

void GetMinDist(int StartNode, int V[NMAX])
{
    for(int i = 1; i <= N; ++ i) V[i] = INF;
    queue<int> Q;
    Q.push(StartNode);
    V[StartNode] = 0;
    
    while(!Q.empty())
    {
        int Node = Q.front();
        Q.pop();
        InQueue[Node] = 0;
        for(vector<pair<int, int> > :: iterator it = GC[Node].begin(); it != GC[Node].end(); ++ it)
            if(V[it -> first] > V[Node] + it -> second)
            {
                V[it -> first] = V[Node] + it -> second;
                if(!InQueue[it -> first])
                    InQueue[it -> first] = 1, Q.push(it -> first);
            }
    }
}

void Build_B()
{
    for(int i = 1; i < CONFMAX; ++ i)
        Bit[i] = Bit[i >> 1] + (i & 1);
}

int GetAns()
{
    memset(Dp, INF, sizeof(Dp));
    Dp[1][0] = 0;
    for(int Conf = 1; Conf < (1 << (K + 1)); ++ Conf)
        for(int i = 0; i <= K; ++ i)
            if(Dp[Conf][i] != INF)
                for(int j = 0; j <= K; ++ j)
                    if(!(Conf & (1 << j)) && Min[i][Special[j]] + 1 >= Bit[Conf] && Dp[Conf ^ (1 << j)][j] > Dp[Conf][i] + Bit[Conf] * Dist[i][Special[j]])
                        Dp[Conf ^ (1 << j)][j] = Dp[Conf][i] + Bit[Conf] * Dist[i][Special[j]];
    
    int Ans = INF;
    for(int i = 0; i <= K; ++ i)
        Ans = min(Ans, Dp[(1 << (K + 1)) - 1][i]);
    return Ans;
}

int main()
{
    freopen("gather.in", "r", stdin);
    freopen("gather.out", "w", stdout);
    
    scanf("%i %i %i", &K, &N, &M);
    for(int i = 1; i <= K; ++ i)
        scanf("%i", &Special[i]);
    
    for(int i = 1; i <= M; ++ i)
    {
        scanf("%i %i %i %i", &A, &B, &C, &D);
        G[A].push_back(make_pair(B, D));
        G[B].push_back(make_pair(A, D));
        GC[A].push_back(make_pair(B, C));
        GC[B].push_back(make_pair(A, C));
    }
    Special[0] = 1;
    
    for(int i = 0; i <= K; ++ i)
        GetMin(Special[i], Min[i]);
    
    for(int i = 0; i <= K; ++ i)
        GetMinDist(Special[i], Dist[i]);
    
    Build_B();
    printf("%i\n", GetAns());
    
    return 0;
}