Cod sursa(job #1145732)

Utilizator andrettiAndretti Naiden andretti Data 18 martie 2014 13:32:52
Problema Gather Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.63 kb
#include<stdio.h>
#include<algorithm>
#include<vector>
#define pb push_back
#define mp make_pair
#define maxn 755
#define mask 1<<16
#define inf 1LL<<60
using namespace std;

struct edge{int node;long long cst;int cap;};
int n,m,K,nh;
int h[maxn],pos[maxn],p[20];
vector<edge> l[maxn],lp[20];
long long d[maxn],s[mask][20],sol;

void read()
{
    int x,y,cost,capacity;
    scanf("%d%d%d",&K,&n,&m);

    for(int i=1;i<=K;i++) scanf("%d",&p[i]);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&x,&y,&cost,&capacity);
        l[x].pb({y,cost,capacity});
        l[y].pb({x,cost,capacity});
    }
}

void swap(int i,int j)
{
    int aux;
    aux=h[i]; h[i]=h[j]; h[j]=aux;
    pos[h[i]]=i; pos[h[j]]=j;
}

void heap_up(int k)
{
    if(k==1) return;
    int i=k/2;
    if(d[h[k]]<d[h[i]]) {swap(i,k); heap_up(i);}
}

void heap_dw(int k)
{
    int i=2*k;
    if(i<=nh)
    {
        if(i+1<=nh && d[h[i+1]]<d[h[i]]) i++;
        if(d[h[i]]<d[h[k]]) {swap(i,k); heap_dw(i);}
    }
}

int extract()
{
    swap(1,nh--);
    pos[h[nh+1]]=0;
    return h[nh+1];
}

void dijkstra(int S,int D)
{
    int k;
    for(int i=1;i<=n;i++) h[i]=i,pos[i]=i,d[i]=inf;
    d[S]=0; nh=n; swap(1,pos[S]);

    while(nh)
    {
        k=extract();
        heap_dw(1);
        for(unsigned int i=0;i<l[k].size();i++)
         if(pos[l[k][i].node] && l[k][i].cap>=D && d[k]+l[k][i].cst<d[l[k][i].node] )
         {
             d[l[k][i].node]=d[k]+1LL*l[k][i].cst;
             heap_up(pos[l[k][i].node]);
         }
    }
}

void build_graph()
{
    for(int i=1;i<=K;i++)
     for(int j=1;j<=K;j++)
     {
         dijkstra(p[i],j);
         for(int k=1;k<=K;k++)
          if(k!=i && d[p[k]]!=inf)
            lp[k].pb({i,d[p[k]],j});
     }
}

void det(int cm,int k,int nr)
{
    int nm,nk;
    long long Min=inf;

    for(unsigned int i=0;i<lp[k].size();i++)
     if( ((cm>>(lp[k][i].node-1))&1) && lp[k][i].cap>=nr-1 )
     {
         nm=cm^(1<<(k-1)); nk=lp[k][i].node;
         if(s[nm][nk]==-1) det(nm,nk,nr-1);
         Min=min(Min,s[nm][nk]+1LL*nr*lp[k][i].cst);
     }
    s[cm][k]=Min;
}

void solve()
{
    for(int i=0;i<(1<<K);i++)
     for(int j=1;j<=K;j++)
      s[i][j]=-1;

    dijkstra(1,-1);
    for(int i=1;i<=K;i++) s[1<<(i-1)][i]=d[p[i]];

    sol=inf;
    for(int i=1;i<=K;i++)
     det((1<<K)-1,i,K),sol=min(sol,s[(1<<K)-1][i]);
}

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

    read();
    build_graph();
    solve();
    printf("%lld",sol);


    fclose(stdin);
    fclose(stdout);
    return 0;
}