Cod sursa(job #2243827)

Utilizator Ruxandra985Nanu Ruxandra Laura Ruxandra985 Data 21 septembrie 2018 14:40:02
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.92 kb
#include <cstdio>
#include <bitset>
#include <vector>
#include <queue>
#include <iostream>
#define INF 1000000000

using namespace std;
bitset <2001> f;
vector < pair <int,int> > v[2001],w[20];
int k,ppoz,n,i,j,vecin,cost,stare,news,nod;
int stop[20],fstop[2001],f2[20][132000],sol[20][132000],d[20][2001];;
priority_queue <pair <int,int> > h;
priority_queue <pair <int,pair <int,int> > > h2;
vector <pair <int,int> > :: iterator it;

inline void dijkstra_simplu(int nod){
    h.push(make_pair(0,nod));
    for (i=1;i<=n;i++){
        if (i!=nod)
            h.push(make_pair(-INF,i));
        d[ppoz][i]=INF;
    }
    d[ppoz][nod]=0;
    while (!h.empty()){
        nod=h.top().second;
        h.pop();
        while (f[nod]){
            if (h.empty())
                return;
            nod=h.top().second;
            h.pop();
        }
        f[nod]=1;
        for (it=v[nod].begin() ; it!=v[nod].end() ; it++){
            vecin=it->first;
            cost=it->second;
            if (cost+d[ppoz][nod]<d[ppoz][vecin]){
                d[ppoz][vecin]=d[ppoz][nod]+cost;
                h.push(make_pair(-d[ppoz][vecin],vecin));
            }
        }
    }
}

inline void dijkstra_complex (){
    h2.push(make_pair(0,make_pair(k-1,(1<<(k-2)))));
    for (i=1;i<=k;i++){
        for (j=0;j<=(1<<k)-1;j++){
            h2.push(make_pair(-INF,make_pair(i,j)));
            sol[i][j]=INF;
        }
    }
    sol[k-1][(1<<(k-2))]=0;
    while (!h2.empty()){
        nod=h2.top().second.first;
        stare=h2.top().second.second;
        h2.pop();
        while (f2[nod][stare]){
            if (h2.empty())
                return;
            nod=h2.top().second.first;
            stare=h2.top().second.second;
            h2.pop();
        }
        if (nod==k && stare==(1<<k)-1) /// AM GASIT SOLUTIA
            return ;
        f2[nod][stare]=1;
        for (it=w[nod].begin() ; it!=w[nod].end() ; it++){
            vecin=it->first;
            cost=it->second;
            news=(stare | (1<<(vecin-1)));
            if (cost+sol[nod][stare]<sol[vecin][news]){
                sol[vecin][news]=sol[nod][stare]+cost;
                h2.push(make_pair(-sol[vecin][news],make_pair(vecin,news)));
            }
        }
    }
}
int main()
{
    FILE *fin=fopen ("ubuntzei.in","r");
    FILE *fout=fopen ("ubuntzei.out","w");
    int m,i,x,y,z,j,ii;
    fscanf (fin,"%d%d%d",&n,&m,&k);
    for (i=1;i<=k;i++){
        fscanf (fin,"%d",&stop[i]);
        fstop[stop[i]]=1;
    }
    k+=2;
    stop[k-1]=1;
    stop[k]=n;
    for (i=1;i<=m;i++){
        fscanf (fin,"%d%d%d",&x,&y,&z);
        v[x].push_back(make_pair(y,z));
        v[y].push_back(make_pair(x,z));
    }
    for (i=0;i<k;i++){
        f.reset();
        ppoz=i;
        dijkstra_simplu (stop[i+1]);
        for (j=i+2;j<=k;j++)
            if (d[ppoz][stop[j]]!=INF){
                w[i+1].push_back(make_pair(j,d[ppoz][stop[j]]));
                w[j].push_back(make_pair(i+1,d[ppoz][stop[j]]));
            }
    }
    // am creat noul graf pe care voi face tot dijkstra dar cu stari
    /// CHECKED
    // dinamica ?
    k-=2;
    if (k==0){
        fprintf (fout,"%d",d[k][n]);
        return 0;
    }
    for (i=1;i<=k;i++){
        for (j=1;j<=(1<<k)-1;j++)
            sol[i][j]=INF;
        sol[i][(1<<(i-1))]=d[i-1][1];
    }
    for (j=1;j<=(1<<k)-1;j++){
            for (i=1;i<=k;i++){
                //if (j==1 && i==1)
                  //  printf ("a");
                if (sol[i][j]==INF)
                    continue;
                for (ii=1;ii<=k;ii++){
                    if (ii!=i && (j & (1<<(ii-1)))==0)
                        sol[ii][j+(1<<(ii-1))]=min(sol[ii][j+(1<<(ii-1))],sol[i][j] + d[i-1][stop[ii]]);
                }
            }
    }
    int ok=INF;
    for (i=1;i<=k;i++)
        ok=min(ok,sol[i][(1<<k)-1]+d[i-1][n]);
    fprintf (fout,"%d",ok);
    return 0;
}