Pagini recente » Cod sursa (job #2246317) | Cod sursa (job #723425) | Cod sursa (job #2196391) | Cod sursa (job #420631) | Cod sursa (job #1965432)
#include <fstream>
#include <queue>
#include <vector>
using namespace std;
ifstream in("gather.in");
ofstream out("gather.out");
const int MAXN = 755;
const int MAXK = 17;
const long long INF = 1ll << 50;
int n,k;
struct muchie
{
int vecin;
int cost;
int capacitate;
};
vector<muchie> vecini[MAXN];
int detinut[MAXK];
void citire()
{
int m;
in >> k >> n >> m;
for (int i = 1;i <= k;++i)
{
in >> detinut[i];
--detinut[i];//numerotam de la zero
}
for (int i = 1;i <= m;++i)
{
int a,b,c,d;
in >> a >> b >> c >> d;
vecini[a - 1].push_back((muchie){b - 1,c,d});
vecini[b - 1].push_back((muchie){a - 1,c,d});
}
}
//d[i][j][k] - costul minim de a ajunge la nodul k, plecand de la detinutul i
// folosind doar muchii cu cost mai mare sau egal cu j
long long d[MAXK][MAXK][MAXN];
//a[i][j] - costul minim de a ajunge la detinutul j, avand ca detinuti ce ne urmaresc
// valorile de 1 din reprezentarea binara a lui i
long long a[1 << MAXK][MAXK];
int nrbiti(int x)
{
int rasp = 0;
while(x != 0)
{
rasp += x & 1;//adunam zero daca nu are bitul 1, adunam 1 altfel
x >>= 1;
}
return rasp;
}
struct nod_dijk
{
int nod;
long long dist;
bool operator < (const nod_dijk &b) const
{
return dist > b.dist;//heap implicit de maxime
}
};
void dijkstra(int sursa, int nrdetinuti, long long D[])
{
priority_queue<nod_dijk> heap;
for (int i = 0;i <= n;++i)
D[i] = INF;
D[sursa] = 0;
heap.push((nod_dijk){sursa, 0});
while(!heap.empty())
{
int nod = heap.top().nod;
int dist = heap.top().dist;
heap.pop();
if (dist > D[nod])
continue;
for (unsigned int i = 0;i < vecini[nod].size();++i)
{
int vecin = vecini[nod][i].vecin;
int cost = vecini[nod][i].cost;
int capacitate = vecini[nod][i].capacitate;
if (capacitate >= nrdetinuti &&
D[vecin] > D[nod] + cost)
{
D[vecin] = D[nod] + cost;
heap.push((nod_dijk){vecin, D[vecin]});
}
}
}
for (int i = 1;i <= n;++i)
if (D[i] < INF)
D[i] *= nrdetinuti + 1;//intra si Gigel aici la cost
}
void prelucrare()
{
for (int j = 0;j <= k + 1;++j)
dijkstra(0, j, d[0][j]);//nodul lui Gigel este zero.
for (int i = 1;i <= k;++i)
for (int j = 0;j <= k + 1;++j)
dijkstra(detinut[i], j, d[i][j]);
for (int i = 0;i < (1 << (k + 1));++i)
for (int j = 0;j <= k;++j)
a[i][j] = INF;
a[1][0] = 0;
for (int i = 2;i < (1 << (k + 1));++i)
{
int nrdetinuti = __builtin_popcount(i) - 2; //nrbiti(i) - 2;
for (int j = 0;j <= k;++j)
if (i & (1 << j))
for (int p = 0;p <= k;++p)
a[i][j] = min(a[i][j],
a[i ^ (1 << j)][p] + d[p][nrdetinuti][detinut[j]]);
}
}
void afisare()
{
long long rasp = INF;
for (int i = 0;i <= k;++i)
rasp = min(rasp, a[(1 << (k + 1)) - 1][i]);
out << rasp << '\n';
}
int main()
{
citire();
prelucrare();
afisare();
return 0;
}