Cod sursa(job #790168)

Utilizator maritimCristian Lambru maritim Data 20 septembrie 2012 16:22:36
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.35 kb
#include<stdio.h>
#include<vector>
#include<queue>
using namespace std;

FILE *f = fopen("ubuntzei.in","r");
FILE *g = fopen("ubuntzei.out","w");

typedef vector<pair<int,int> >::iterator it;

#define MaxC 20
#define MaxN 2010
#define Max2C ((1<<15)+100)
#define INF (1<<29)

int N,M,K,Sol;
int C[MaxC],D[MaxN],inCoada[MaxN];
int B[MaxC][MaxC],Best[Max2C][MaxC];
vector<pair<int,int> > A[MaxN];

void citire(void)
{
    int a,b,c;

    fscanf(f,"%d %d %d",&N,&M,&K);
    for(int i=0;i<K;i++)
        fscanf(f,"%d ",&C[i]);

    for(int i=1;i<=M;i++)
    {
        fscanf(f,"%d %d %d",&a,&b,&c);
        A[a].push_back(make_pair(b,c));
        A[b].push_back(make_pair(a,c));
    }
}

inline void Initializare(void)
{
    for(int i=1;i<=N;i++)
        D[i] = INF;
}

inline void BellmanFord(int a)
{
    queue<int> Q;

    Initializare();

    D[a] = 0; inCoada[a] = 1;

    for(Q.push(a);!Q.empty();inCoada[Q.front()] = 0,Q.pop())
        for(it i=A[Q.front()].begin();i<A[Q.front()].end();i++)
            if(D[i->first] > D[Q.front()] + i->second)
            {
                D[i->first] = D[Q.front()] + i->second;
                if(!inCoada[i->first])
                    inCoada[i->first] = 1, Q.push(i->first);
            }
}

void CreareDrumuri(void)
{
    for(int i=0;i<K;i++)
    {
        BellmanFord(C[i]);
        
        for(int j=0;j<K;j++)
            B[i][j] = D[C[j]];
    }
}

void InitializareDinamica(void)
{
    BellmanFord(1);

    for(int i=0;i< 1<<K;i++)
        for(int j=0;j<K;j++)
            Best[i][j] = INF;

    for(int i=0;i<K;i++)
        Best[0][i] = D[N];

    for(int i=0;i<K;i++)
        Best[(1<<i)][i] = D[C[i]]; 
}

void Dinamica(void)
{
    InitializareDinamica();

    for(int i=0;i< 1<<K;i++)
        for(int j=0;j<K;j++)
            if((1<<j) & i)
                for(int k=0;k<K;k++)
                    if(! ((1<<k) & i))
                        Best[i^(1<<k)][k] = min(Best[i^(1<<k)][k],
                                                Best[i][j]+B[j][k]);
}

void ObtineSolutia(void)
{
    BellmanFord(N);

    Sol = INF;

    for(int i=0;i<K;i++)
        Sol = min(Sol,Best[(1<<K)-1][i]+D[C[i]]);
}

void Rezolvare(void)
{
    if(!K)
    {
        BellmanFord(1);
        Sol = D[N];
        
        return ;
    }

    CreareDrumuri();

    Dinamica();

    ObtineSolutia();
}

int main()
{
    citire();
    Rezolvare();

    fprintf(g,"%d\n",Sol);
}