Cod sursa(job #1016940)

Utilizator Impaler_009Mihai Nitu Impaler_009 Data 26 octombrie 2013 22:30:19
Problema Gather Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.94 kb
#include <fstream>
#include <vector>
#include <cstring>

#define maxn 760
#define vint vector<node>::iterator
#define inf 1LL*1000000000000

using namespace std;

ifstream fin("gather.in");
ofstream fout("gather.out");

struct node
{
    int x,d,lim;
};

int n,k,m,x,y,w,z,hsize;
long long dp[1<<15][16],d[maxn],dist[16][16][16];
int h[maxn],hpoz[maxn],v[16],bits[1<<16];
vector <node> G[maxn];

int get_bits (int x)
{
    int nr=0;

    while (x!=0)
    {
        nr += (x&1);
        x>>=1;
    }
    return nr;
}


void read ()
{
    fin>>k>>n>>m;

    for (int i=1; i<=k; ++i)
    {
        fin>>x;
        v[i] = x;
    }

    for (int i=1; i<=m; ++i)
    {
        fin>>x>>y>>w>>z;

        node in;
        in.x = y;
        in.d = w;
        in.lim = z;

        G[x].push_back (in);

        in.x = x;

        G[y].push_back (in);
    }
}

inline int father (const int x)
{
    return x>>1;
}

inline int left_son (const int x)
{
    return x<<1;
}

inline int right_son (const int x)
{
    return (x<<1)+1;
}

void upheap (int poz)
{
    int pullout = h[poz];

    while (d[pullout] < d[h[father(poz)]])
    {
        h[poz] = h[father(poz)];
        hpoz[h[poz]] = poz;
        poz >>=1;
    }

    h[poz] = pullout;
    hpoz[h[poz]] = poz;
}

void downheap (int poz)
{
    int pullout = h[poz],ok=0;

    while (ok!=-1)
    {
        ok = -1;

        if (left_son(poz) <= hsize && d[pullout] > d[h[left_son(poz)]])
            ok =0;
        if (right_son(poz) <= hsize && d[pullout] > d[h[right_son(poz)]])
        {
            if (ok==0)
            {
                if (d[h[right_son(poz)]] < d[h[left_son(poz)]])
                    ok = 1;
            }
            else ok = 1;
        }

        if (ok!=-1)
        {
            h[poz] = h[(poz<<1)+ok];
            hpoz[h[poz]] = poz;
            poz = (poz<<1)+ok;
        }
    }

    h[poz] = pullout;
    hpoz[h[poz]] = poz;
}

void dijkstra (int x, int l)
{
    for (int i=1; i<=n+1; ++i)
    {
        h[i] = i;
        hpoz[i] = i;
        d[i] = inf;
    }

    hsize = n;
    d[x] = 0;
    swap (h[x],h[1]);
    swap (hpoz[x],hpoz[1]);

    while (d[h[1]] != inf)
    {
        int c = h[1];

        h[1] = h[hsize];
        hpoz[h[1]] = 1;
        h[hsize] = n+1;
        --hsize;

        downheap (hpoz[h[1]]);

        for (vint it = G[c].begin(); it!=G[c].end(); ++it)
        {
            if (it->lim < l)
            {
                continue;
            }

            if (d[it->x] > d[c] + it->d*(l+1))
            {
                d[it->x] = d[c] + it->d*(l+1);
                upheap (hpoz[it->x]);
            }
        }
    }
}

void paths ()
{
    dijkstra (1,0);

    for (int i=1; i<=k; ++i)
    {
        dp[1<<(i-1)][i] = d[v[i]];
    }

    for (int i=1; i<k; ++i)
    {
        for (int j=1; j<=k; ++j)
        {
            dijkstra (v[j],i);

            for (int h=1; h<=k; ++h)
            {
                dist[i][j][h] = d[v[h]];
            }
        }
    }
}

long long DP ()
{
    for (int i=1; i<(1<<k); ++i)
    {
        for (int j=1; j<=k; ++j)
        {
            if (dp[i][j] == inf)
                continue;

            for (int h=1; h<=k; ++h)
            {
                if (i | (1<<(h-1)) != i)
                {
                    dp[i|(1<<(h-1))][h] = min (dp[i|(1<<(h-1))][h], dp[i][j] + dist[bits[i]][j][h]);
                }
            }
        }
    }

    long long ans = inf;

    for (int i=1; i<=k; ++i)
    {
        ans = min (ans,dp[(1<<k)-1][i]);
    }

    return ans;
}

int main()
{
    read ();

    for (int i=0; i<(1<<k); ++i)
    {
        bits[i] = get_bits(i);
    }

    for (int i=0; i<(1<<k); ++i)
    {
        for (int j=1; j<=k; ++j)
                dp[i][j] = inf;
    }

    paths ();

    fout<<DP ();

    return 0;
}