Cod sursa(job #679250)

Utilizator rootsroots1 roots Data 12 februarie 2012 22:28:42
Problema Gather Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.12 kb
#include <fstream>
#include <vector>
#include <cstring>
#include <algorithm>

#define maxN 751
#define maxK 16

#define INF 0x7fffffff

using namespace std;

vector <int> g[maxN];

int dist[maxN][maxN];
int cnt[maxN][maxN];
int cost[maxK][maxK][maxK];
int d[maxN];
int h[maxN];
int v[maxK];

int K,N;

inline bool cmp(const int &a,const int &b)
{
    return d[a]>d[b];
}

inline void dij(int nod,int num)
{
    memset(h,0,sizeof(h));
    for(int i=1;i<=N;++i) d[i]=INF;

    h[0]=1;
    h[1]=nod;
    d[nod]=0;

    for(;h[0];)
    {
        nod=h[1];
        pop_heap(h+1,h+h[0]+1,cmp);
        --h[0];

        for(vector <int>::iterator it=g[nod].begin();it!=g[nod].end();++it)
            if(d[*it]>d[nod]+(num+1)*dist[nod][*it]&&num<=cnt[nod][*it])
            {
                d[*it]=d[nod]+(num+1)*dist[nod][*it];
                h[++h[0]]=*it;
                push_heap(h+1,h+h[0]+1,cmp);
            }
    }
}

struct hp
{
    int nod,cod;
};

int ds[100001][maxK];

inline bool cmpx(const hp &a,const hp &b)
{
    int xa=0;
    for(int aux=a.cod;aux;aux>>=1)
        if(aux&1) ++xa;

    int xb=0;
    for(int aux=b.cod;aux;aux>>=1)
        if(aux&1) ++xb;

    if(ds[xa][a.nod]!=ds[xb][b.nod]) return ds[xa][a.nod]>ds[xb][b.nod];
    return xa>xb;
}

inline void dijx()
{
    hp h[maxK*maxK+1];
    int size=0;

    memset(h,0,sizeof(h));
    for(int i=0;i<=(1<<K)-1;++i)
        for(int j=0;j<=K;++j)
            ds[i][j]=INF;
    ds[0][0]=0;

    size=1;
    h[1].nod=0;
    h[1].cod=0;

    for(int nod,cod;size;)
    {
        nod=h[1].nod;
        cod=h[1].cod;
        pop_heap(h+1,h+size+1,cmpx);
        --size;

        int x=0;
        for(int aux=cod;aux;aux>>=1)
            if(aux&1) ++x;

        for(int i=1;i<=K;++i)
            if((cod&(1<<(i-1)))==0)
                if(ds[cod+(1<<(i-1))][i]>ds[cod][nod]+cost[x][nod][i]&&cost[x][nod][i])
                {
                    ds[cod+(1<<(i-1))][i]=ds[cod][nod]+cost[x][nod][i];
                    if(x+1<K)
                    {
                        h[++size].nod=i;
                        h[size].cod=cod+(1<<(i-1));
                        push_heap(h+1,h+size+1,cmpx);
                    }
                }
    }
}

ifstream in;
ofstream out;

int main()
{
    int M,x,y;

    in.open("gather.in");

    in>>K>>N>>M;
    v[0]=1;
    for(int i=1;i<=K;++i) in>>v[i];
    for(;M--;)
    {
        in>>x>>y;
        in>>dist[x][y];
        in>>cnt[x][y];

        cnt[y][x]=cnt[x][y];
        dist[y][x]=dist[x][y];

        g[x].push_back(y);
        g[y].push_back(x);
    }

    in.close();

    out.open("gather.out");

    memset(cost,0,sizeof(cost));

    for(int i=0;i<K;++i)
        for(int j=0;j<=K;++j)
        {
            dij(v[j],i);

            for(int k=1;k<=K;++k)
                if(d[v[k]]!=INF&&d[v[k]])
                    cost[i][j][k]=d[v[k]];
        }

    dijx();

    int min=INF;
    for(int i=1;i<=K;++i)
        if(min>ds[(1<<K)-1][i]) min=ds[(1<<K)-1][i];
    out<<min<<'\n';

    out.close();

    return 0;
}