Cod sursa(job #677820)

Utilizator GavrilaVladGavrila Vlad GavrilaVlad Data 10 februarie 2012 18:29:40
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.98 kb
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;

#define maxk 17
#define maxn 2010
#define inf 1000000000

int n, m, k, a, b, c;
int d[1<<maxk][maxk];
int dist[maxk][maxk], poz[maxk], conf[maxk];
int dmin[maxn], f[maxn], q[maxn];
vector<int> v[maxn], w[maxn];

void bellmanford(int start, int where)
{
    int q0=1, nod, fiu;

    memset(f, 0, sizeof(f));

    q[q0]=start;
    for(int i=1; i<=n; ++i)
        dmin[i]=inf;

    dmin[start]=0;
    f[start]=1;
    for(int i=1; i<=q0; ++i)
    {
        nod=q[i%n];
        f[nod]=0;
        for(int j=0; j<v[nod].size(); ++j)
        {
            fiu=v[nod][j];
            if(dmin[fiu]>dmin[nod]+w[nod][j])
            {
                dmin[fiu]=dmin[nod]+w[nod][j];
                if(f[fiu]==0)
                {
                    ++q0;
                    q[q0%n]=fiu;
                    f[fiu]=1;
                }
            }
        }
    }
    for(int i=0; i<k; ++i)
        dist[where][i]=dmin[poz[i]];
}

int main()
{
    freopen("ubuntzei.in", "r", stdin);
    freopen("ubuntzei.out", "w", stdout);

    scanf("%d%d", &n, &m);
    scanf("%d", &k);
    for(int i=1; i<=k; ++i)
        scanf("%d", &poz[i]);
    poz[++k]=n;
    ++k;
    for(int i=1; i<=m; ++i)
    {
        scanf("%d%d%d", &a, &b, &c);
        v[a].push_back(b);
        v[b].push_back(a);
        w[a].push_back(c);
        w[b].push_back(c);
    }

    poz[0]=1;
    for(int i=0; i<k; ++i)
        bellmanford(poz[i], i);

    d[1][0]=0;

    for(int i=0; i<(1<<k); ++i)
    {
        for(int j=0; j<k; ++j)
            conf[j]=((i>>j)&1);
        for(int j=0; j<k; ++j)
        {
            if(i!=1 || j!=0)
                d[i][j]=inf;
            if(conf[j]==0)
                continue;
            for(int l=0; l<k; ++l)
            {
                if(l==j || conf[l]==0)
                    continue;
                d[i][j]=min(d[i][j], d[i-(1<<j)][l]+dist[j][l]);
            }
        }
    }

    printf("%d\n", d[(1<<k)-1][k-1]);
    return 0;
}