Cod sursa(job #2649820)

Utilizator victorzarzuZarzu Victor victorzarzu Data 16 septembrie 2020 16:01:52
Problema Gather Scor 20
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.68 kb
#include <bits/stdc++.h>
#define point pair<int, int> 
#define dist first
#define nod second
#define oo 0x3f3f3f3f

using namespace std;
ifstream fin("gather.in");
ofstream fout("gather.out");

int n, k, m;
vector<tuple<int, int, int>> g[750];
vector<point> detinuti;
int distanta[17][17], dp[(1 << 15) + 5][17], graf[17][17][17];
queue<int> q;
bitset<755> viz;

void Read()
{
  int w, x, y, z, nr = 0;
  fin>>k>>n>>m;
  detinuti.push_back({1, ++nr});
  for(int i = 1;i <= k;++i)
    fin>>w, detinuti.push_back({w, ++nr});
  for(int i = 1;i <= m;++i)
  {
    fin>>w>>x>>y>>z;
    g[w].push_back({x, y, z}); g[x].push_back({w, y, z});
  }
}

void bellman(int start)
{
  viz.reset();
  memset(distanta, oo, sizeof(distanta));
  for(int i = 0;i <= k;++i)
    distanta[start][i] = 0;
  q.push(start);
  viz.set(start);
  int nod, vecin, cost, cap;
  bool mod = false;

  while(!q.empty())
  {
    nod = q.front();
    q.pop();

    for(auto it : g[nod])
    {
      vecin = get<0>(it), cost = get<1>(it), cap = get<2>(it);
      mod = false;

      for(int i = 0;i <= cap;++i)
        for(int j = i;j <= cap;++j)
          if(distanta[vecin][i] > distanta[nod][j] + cost)
          {
            mod = true;
            distanta[vecin][i] = distanta[nod][j] + cost;
          }
      if(!viz.test(vecin) && mod)
        q.push(vecin);
      viz.set(vecin);
    }

    viz.reset(vecin);
  }
}

void solve()
{
  memset(dp, oo, sizeof(dp));
  dp[0][1] = 0;
  for(int i = 2;i <= k + 1;++i)
    dp[1 + (1 << (i - 1))][i] = graf[1][i][0]; 
  int nr;
  for(int i = 2;i < (1 << (k + 1));++i)
    if(1 & i)
    {
      nr = 0;
      for(int h = 1;h <= k;++h)
        if(i & (1 << h)) ++nr;
      if(nr <= 1)
        continue;
      for(int j = 1;j <= k + 1;++j)
        for(int h = 1;h <= k + 1;++h)
          if(j != h)
          {
            if(j > 1 && i & (1 << (j - 1)))
              dp[i][j] = min(dp[i][j], dp[i - (1 << (j - 1))][h] + nr * graf[j][h][nr - 1]);
            dp[i][j] = min(dp[i][j], dp[i][h] + (nr + 1) * graf[j][h][nr]);
          }
    }
    int rez = oo;
    for(int i = 1;i <= k + 1;++i)
      rez = min(rez, dp[(1 << (k + 1)) - 1][i]);
    fout<<rez;
}

void make_graph()
{
  int nr = 0;
  for(auto it : detinuti)
    {
      ++nr;
      bellman(it.first);
      for(auto it1 : detinuti)
        for(int i = 0;i <= k;++i)
          if(it.first != it1.first && distanta[it1.first][i] < oo)
            graf[it.second][it1.second][i] = distanta[it1.first][i];
    }
  /*for(int i = 1;i <= k + 1;++i, cout<<'\n')
    for(int j = 1;j <= k + 1;++j)
      for(int h = 0;h <= k;++h)
        if(i != j)
           cout<<i<<" "<<j<<" "<<graf[i][j][h]<<" "<<h<<'\n';*/
}

int main()
{
  Read();
  make_graph();
  solve();
  return 0;
}