Cod sursa(job #3193459)

Utilizator veveve ve veve Data 14 ianuarie 2024 17:42:03
Problema Ubuntzei Scor 75
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.75 kb
#include <iostream>
#include <fstream>
#include <queue>
#include <vector>

#define N 2005
#define pinf 2e+8
using namespace std;

int D2[20][131100];

long long D[N];
struct Nod
{
   int nod,s;
   long long cost;
};
class Compar  //vezi priority_queue.pdf
{
 public:
 bool operator()( Nod &x, Nod &y)
 {
    if(x.cost>y.cost) return true; // ordine crscatoare
    else return false;
 }
};

priority_queue< Nod, vector< Nod >, Compar > coada;

int n,m,nrs,vk[20],k;

vector < vector<pair<int,int> > >L(N);
vector < vector < Nod > >L2(20);
ifstream f("ubuntzei.in");
ofstream g("ubuntzei.out");

int sel[2005][2];

void dijkstra2(int r)
{
    int i,poz,c,j,sub,w;

    for(i=1;i<=k+2;i++)
        for(j=0;j<=nrs;j++)
            D2[i][j]=pinf;

    Nod x,y;
    x.cost=0;x.nod=r;x.s=0;
    if(sel[r][0])  //face parte din mult
    {
        x.s=(x.s|(1<<sel[r][1]));
        D2[sel[r][1]][x.s]=0;
    }
    else D2[sel[r][1]][0]=0;

     coada.push(x);
    while(!coada.empty())
    {

        x=coada.top(); //cout<<x.nod<<endl;
        coada.pop();
        if(x.nod==n and x.s==nrs) break;
       // cout<<x.nod<<" "<<x.s<<endl;

        if(D2[sel[x.nod][1]][x.s]==x.cost)  //daca poz e la distanta minima fata de sursa
        {

          w=sel[x.nod][1];
          for(i=0;i<L2[w].size();i++)
          {
              // sub=(sub|(1<<sel[L2[sel[x.nod][1]][i].first][1]));
              sub=(x.s|L2[w][i].s);

            if(D2[sel[L2[w][i].nod][1]][sub]>D2[w][x.s]+L2[w][i].cost ) //daca putem imbunatati distanta
            {
                D2[sel[L2[w][i].nod][1]][sub]=D2[w][x.s]+L2[w][i].cost;
                y.nod=L2[w][i].nod;
                y.cost=D2[sel[L2[w][i].nod][1]][sub];
                y.s=sub;
                coada.push(y);
                   //adaugam nodul si distanta imbunatatita in coada
            }
          }
        }
    }

}
 void dijkstra1(int r)
{
    int i,poz,c,j,sub;

    for(i=1;i<=n;i++)
       D[i]=pinf;

    Nod x,y;
    x.cost=0;x.nod=r;x.s=0;
    if(sel[r][0])  //face parte din mult
    {
        x.s=(x.s|(1<<sel[r][1]));
    }
    D[r]=0;

    coada.push(x);

    while(!coada.empty())
    {

        x=coada.top();
        coada.pop();

        if(D[x.nod]==x.cost)  //daca poz e la distanta minima fata de sursa
        {
          if(x.nod!=r)
            if(sel[x.nod][0]) L2[sel[r][1]].push_back(x);
          //parcurgem lista de adiacenta a lui poz
          for(i=0;i<L[x.nod].size();i++)
          {
            sub=x.s;
            if(sel[L[x.nod][i].first][0])  //face parte din mult
            {
                sub=(sub|(1<<sel[L[x.nod][i].first][1]));
            }

            if(D[L[x.nod][i].first]>D[x.nod]+L[x.nod][i].second ) //daca putem imbunatati distanta
            {
                D[L[x.nod][i].first]=D[x.nod]+L[x.nod][i].second;
                y.nod=L[x.nod][i].first;
                y.cost=D[L[x.nod][i].first];
                y.s=sub;
                coada.push(y);
                   //adaugam nodul si distanta imbunatatita in coada
            }
          }
        }
    }


}
int main()
{
     int x,y,c,i;

   f>>n>>m>>k;
   for(i=1;i<=k;i++)
   {
       f>>c;vk[i]=c;
       sel[c][0]=1;
       sel[c][1]=i;
       nrs=(nrs|(1<<i));

   }
   vk[0]=1;sel[1][0]=1; sel[1][1]=0; nrs=(nrs|(1<<0));
   vk[k+1]=n;sel[n][0]=1; sel[n][1]=k+1; nrs=(nrs|(1<<k+1));
  // cout<<nrs;
   for(i=1;i<=m;i++)
   {
      f>>x>>y>>c; //cout<<7<<endl;
      L[x].push_back(make_pair(y,c));
      L[y].push_back(make_pair(x,c));
   }
;
   dijkstra1(1);
   for(i=1;i<=k+1;i++) dijkstra1(vk[i]);


  dijkstra2(1);
   g<<D2[sel[n][1]][nrs]<<" ";

   f.close();
   g.close();

    return 0;
}