Cod sursa(job #1911294)

Utilizator matystroiaStroia Matei matystroia Data 7 martie 2017 20:01:51
Problema Ubuntzei Scor 65
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.67 kb
#include <fstream>
#include <vector>
#include <queue>
#include <functional>
using namespace std;

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

const int N=2005, K=15, INF=50000000;

typedef pair<int,int> ipair;

int n, m, k, d[N][1<<K], pri[N], prie[N], d2[N];
vector<pair<int,int>> ad[N];
vector<pair<int,int>> adk[N];

struct el{int nod, dist, mask;};

class cmp
{
public:
    bool operator()(el a, el b)
    {
        return a.dist<b.dist;
    }
};

int main()
{
    fin>>n>>m>>k;
    fill_n(pri, n+1, -1);
    for(int i=0;i<k;++i)
    {
        int j;
        fin>>j;
        pri[j]=i;
        prie[i]=j;
    }
    pri[1]=k;
    pri[n]=k+1;

    prie[k]=1;
    prie[k+1]=n;

    for(int i=0;i<m;++i)
    {
        int x, y, z;
        fin>>x>>y>>z;
        ad[x].push_back(make_pair(y, z));
        ad[y].push_back(make_pair(x, z));
    }

    for(int i=1;i<=n;++i)
        for(int mask=0;mask<(1<<k);++mask)
            d[i][mask]=INF;

    for(int i=0;i<k+2;++i)
    {
        for(int j=1;j<=n;++j)
            d2[j]=INF;

        d2[prie[i]]=0;
        priority_queue<ipair, vector<ipair>, greater<ipair>> pq;
        pq.push(make_pair(0, prie[i]));

        while(pq.size())
        {
            int nod=pq.top().second;
            int dist=pq.top().first;
            pq.pop();

            if(dist!=d2[nod]) continue;

            for(auto muc:ad[nod])
            {
                if(d2[nod]+muc.second<d2[muc.first])
                    d2[muc.first]=d2[nod]+muc.second, pq.push(make_pair(d2[muc.first], muc.first));
            }
        }

        for(int j=0;j<k+2;++j)
            if(pri[prie[j]]!=-1 && j!=i && d2[prie[j]]!=INF)
                adk[prie[i]].push_back(make_pair(prie[j], d2[prie[j]]));
    }


    priority_queue<el, vector<el>, cmp> pq;
    pq.push({1, 0, 0});
    d[1][0]=0;

    while(pq.size())
    {
        int nod=pq.top().nod;
        int mask=pq.top().mask;
        int dist=pq.top().dist;
        pq.pop();

        if(dist!=d[nod][mask])
            continue;

        for(auto v:adk[nod])
        {
            int vecin=v.first;
            int muchie=v.second;

            if((vecin==n||vecin==1)&&d[nod][mask]+muchie<d[vecin][mask])
                d[vecin][mask]=d[nod][mask]+muchie, pq.push({vecin, d[vecin][mask], mask});

            bool visited=mask&(1<<pri[vecin]);
            if(!visited&&d[nod][mask]+muchie < d[vecin][mask|(1<<pri[vecin])])
                d[vecin][mask|(1<<pri[vecin])]=d[nod][mask]+muchie, pq.push({vecin, d[vecin][mask|(1<<pri[vecin])], mask|(1<<pri[vecin])});
        }
    }
    fout<<d[n][(1<<k)-1];
    return 0;
}