#include <stdio.h>
#include <vector>
#include <queue>
#include <map>
using namespace std;
#define MAX_CELLS 752
#define INF 2000000000
struct muchie {
int nod; // nodul spre care merge muchia
int lung; // lungimea muchiei
int cap; // capacitatea maxima
};
struct stare {
int nod; // nodul in care se afla gigel
int det; // ce detinuti avem cu noi, codificati pe biti (al -ilea bit setat, avem al i-lea detinut)
int lung; // ce lungime am parcurs
};
// ce codificare ne trebuie pt. evadare (toti detinutii)
int full[] = { 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767 };
int k, n, m; // nr de detinuti, nr celule, nr. muchii
map<int, int> detinuti; // ce detinut(nr) e in celula i
vector<muchie> a[MAX_CELLS]; // ce muchii pornesc din nodul i
queue<stare> Q; // coada starilor
int dp[MAX_CELLS][(1<<16)+8]; // am ajuns pana in i cu detinutii codificati ca j, parcurgang lungimea minima
int rez = INF; // raspunsul
int main()
{
int nod1, nod2, auxlung, auxcap;
muchie currm;
stare curr;
int curr_nod, curr_det, curr_lung, auxdet, cntdet;
FILE *fin = fopen("gather.in", "r");
fscanf(fin, "%d%d%d", &k, &n, &m);
for (int i = 0; i < k; ++i)
{
fscanf(fin, "%d", &nod1);
detinuti[nod1] = i;
}
for (int i = 0; i < m; ++i)
{
fscanf(fin, "%d%d%d%d", &nod1, &nod2, &auxlung, &auxcap);
currm.nod = nod2;
currm.lung = auxlung;
currm.cap = auxcap;
a[nod1].push_back(currm);
currm.nod = nod1;
a[nod2].push_back(currm);
}
fclose(fin);
// init
for (int i = 0; i <= n; ++i)
for (int j = 0; j <= ((1 << (k+1)) + 3); ++j)
dp[i][j] = INF;
// pornim din celula 0, spre celula 1 (lungime 0)
curr.nod = 0;
curr.det = 0;
curr.lung = 0;
Q.push(curr);
// legam celula 0 de 1
currm.nod = 1;
currm.lung = 0;
currm.cap = 2000000000;
a[0].push_back(currm);
while (!Q.empty())
{
curr = Q.front();
Q.pop();
curr_nod = curr.nod;
curr_det = curr.det;
curr_lung = curr.lung;
auxdet = curr.det;
//
if (auxdet == full[k]) // daca am strans toti detinutii
if (rez > curr_lung)
rez = curr_lung;
// daca avem sau am avut in coada o stare mai buna decat cea curenta, ignora
if (dp[curr_nod][curr_det] < curr_lung)
continue;
// nu ii zicem detinutului planul sau celula nu are detinut
cntdet = 0; // nr de detinuti care ii avem cu noi
for (int i = 0; i <= k; ++i)
if (((auxdet >> i) & 1))
cntdet++;
for (int j = 0; j < a[curr_nod].size(); ++j)
if (a[curr_nod][j].cap >= cntdet)
if (dp[a[curr_nod][j].nod][auxdet] > curr_lung + (cntdet+1) * a[curr_nod][j].lung)
{
dp[a[curr_nod][j].nod][auxdet] = curr_lung + (cntdet+1) * a[curr_nod][j].lung;
curr.nod = a[curr_nod][j].nod;
curr.det = auxdet;
curr.lung = curr_lung + (cntdet+1) * a[curr_nod][j].lung;
Q.push(curr);
}
// daca avem detinut
if (detinuti.find(curr_nod) != detinuti.end())
{
// ii spunem
auxdet |= (1 << detinuti[curr_nod]);
if (auxdet == full[k]) // daca am strans toti detinutii
if (rez > curr_lung)
rez = curr_lung;
cntdet = 0; // nr de detinuti care ii avem cu noi
for (int i = 0; i <= k; ++i)
if (((auxdet >> i) & 1))
cntdet++;
for (int j = 0; j < a[curr_nod].size(); ++j)
if (a[curr_nod][j].cap >= cntdet)
if (dp[a[curr_nod][j].nod][auxdet] > curr_lung + (cntdet+1) * a[curr_nod][j].lung)
{
dp[a[curr_nod][j].nod][auxdet] = curr_lung + (cntdet+1) * a[curr_nod][j].lung;
curr.nod = a[curr_nod][j].nod;
curr.det = auxdet;
curr.lung = curr_lung + (cntdet+1) * a[curr_nod][j].lung;
Q.push(curr);
}
}
}
FILE *fout = fopen("gather.out", "w");
fprintf(fout, "%d\n", rez);
fclose(fout);
return 0;
}