#include <bits/stdc++.h>
using namespace std;
const int N = 10000,M = N * 100;
const long long inf = LLONG_MAX >> 5;
class FlowGraph
{
private:
    int head[N],v[M],nxt[M],c[M],ptr,t;
    long long w[M],cost;
    inline void padd_edge(int uu,int vv,long long ww,int cc)
    {
        v[ptr] = vv;w[ptr] = ww;c[ptr] = cc;
        nxt[ptr] = head[uu];head[uu] = ptr++;
    }
    int dis[N],id[N],cur[N];bool vis[N];
    bool spfa(int s,int t)
    {
        memset(vis,0,sizeof(vis));
        memset(dis,-1,sizeof(dis));
        queue<int> q;q.push(s);
        dis[s] = 0;id[s] = 1;
        while (!q.empty())
        {
            int nd = q.front();
			q.pop();vis[nd] = 0;
            for (int i = head[nd];i != -1;i = nxt[i])
                if (w[i] && (dis[v[i]] == -1 || dis[v[i]] > dis[nd] + c[i]))
                {
                    dis[v[i]] = dis[nd] + c[i];
                    if (!vis[v[i]])
                    {
                        vis[v[i]] = 1;q.push(v[i]);
                    }
                }
        }
        return dis[t] != -1;
    }
    long long dfs(int pos,long long flow)
    {
        if (pos == t) return flow;
        vis[pos] = 1;
        long long tmp = flow;
        for (int i = cur[pos] != -1 ? cur[pos] : head[pos];i != -1;i = nxt[i])
            if (!vis[v[i]] && w[i] && dis[v[i]] == dis[pos] + c[i])
            {
                cur[pos] = i;
                long long fl = dfs(v[i],min(flow,w[i]));
                cost += fl * c[i];
                w[i] -= fl;w[i ^ 1] += fl;
                flow -= fl;
                if (!flow) break;
            }
        return tmp - flow;
    }
public:
    FlowGraph()
    {memset(head,-1,sizeof(head));memset(nxt,-1,sizeof(nxt));}
    inline void add_edge(int uu,int vv,long long ww,int cc)
    {
        padd_edge(uu,vv,ww,cc);padd_edge(vv,uu,0,-cc);
    }
    long long dinic(int s,int t)
    {
        cost = 0;this->t = t;
        while (spfa(s,t))
        {
            memset(cur,-1,sizeof(cur));dfs(s,inf);
        }
        return cost;
    }
};
FlowGraph g;
int n,m,kk,c,d,a[55];
int main ()
{
    ios::sync_with_stdio(false);
    cin >> n >> m >> kk >> c >> d;
    for (int i = 1;i <= kk;i++) cin >> a[i];
    int s = 0,t = n * 100 + 1;
    for (int i = 1;i <= 100;i++) g.add_edge(i,t,inf,0);
    for (int i = 1;i <= kk;i++) g.add_edge(s,(a[i] - 1) * 100 + 1,1,0);
    for (int i = 2;i <= n;i++)
        for (int j = 1;j < 100;j++)
            g.add_edge((i - 1) * 100 + j,(i - 1) * 100 + j + 1,inf,c);
    int t1,t2;
    for (int _ = 1;_ <= m;_++)
    {
        cin >> t1 >> t2;
        for (int i = 1;i < 100;i++)
            for (int j = 1;j <= kk;j++) //其实不用枚举到kk，枚举到25左右即可
            {
                int val = c + d * (j * j - (j - 1) * (j - 1));
                g.add_edge((t1 - 1) * 100 + i,(t2 - 1) * 100 + i + 1,1,val);
                g.add_edge((t2 - 1) * 100 + i,(t1 - 1) * 100 + i + 1,1,val);
            }
    }
    cout << g.dinic(s,t) << endl;
    return 0;
}
// 最小费用流 珂以利用流量来处理多人走同一条路的情况


#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL _INF = 0xc0c0c0c0c0c0c0c0;
const LL mod =  (int)1e9+7;
const int Z = 100;
const int N = Z * Z;
const int M = Z * Z * Z * 3;
int px[N], py[N];
int head[N], to[M], ct[M], w[M], nt[M];
int d[N], vis[N];
int pre[N], id[N];
int s, t, tot;

void add(int u, int v, int flow, int cost){
    to[tot] = v; ct[tot] = cost;
    w[tot] = flow; nt[tot] = head[u]; head[u] = tot++;

    to[tot] = u; ct[tot] = -cost;
    w[tot] = 0; nt[tot] = head[v]; head[v] = tot++;
}
void init(){
    memset(head, -1, sizeof(head));
    tot = 0;
}
int spfa(int s, int t){
    queue<int> q;
    memset(d, inf, sizeof(d));
    memset(vis, 0, sizeof(vis));
    memset(pre, -1, sizeof(pre));
    d[s] = 0;
    q.push(s);
    while(!q.empty()){
        int u = q.front(); q.pop();
        vis[u] = 0;
//        cout << u << " " << d[u] << endl;
        for(int i = head[u]; ~i; i = nt[i]){
            if(w[i] > 0 && d[to[i]] > d[u] + ct[i]){
                d[to[i]] = d[u] + ct[i];
                pre[to[i]] = u;
                id[to[i]] = i;
//                if(to[i] == 201) cout << "Updata " << u << " " << to[i] <<" " << d[to[i]] <<endl;
                if(!vis[to[i]]){
                    vis[to[i]] = 1;
                    q.push(to[i]);
                }
            }
        }

    }
//    cout << d[t] << "? "<< endl;
    return d[t] < inf;
}
int MaxFlow(int s, int t){
    int Mi = inf;
    int sum = 0;
    int tt = 0;
//    cout << s << " ss " << t  << endl;
    while(spfa(s, t)){
        Mi = inf;
        for(int i = t; i != s; i = pre[i])
            Mi = min(Mi, w[id[i]]);
        for(int i = t; i != s; i = pre[i]){
            w[id[i]] -= Mi;
            w[id[i]^1] += Mi;
        }
        tt += Mi;
        sum += d[t] * Mi;
//        cout << d[t] << endl;
//        cout << "asd" << endl;
    }
    return sum;
}
int main(){
    init();
    int n, m, k, c, d;
    scanf("%d%d%d%d%d", &n, &m, &k, &c, &d);
    int s = 0, t = n * 100 + 1;
    for(int i = 1; i <= 100; ++i)
        add(i, t, 100, 0);
    for(int i = 1, v; i <= k; ++i){
        scanf("%d" , &v);
        add(s, (v-1)*100+1, 1, 0);
    }
    for(int i = 1; i <= n; ++i){
        for(int j = 1; j < 100; ++j){
            add((i-1)*100 + j, (i-1)*100 + j + 1, 100, c);
        }
    }
    for(int i = 1, u, v; i <= m; ++i){
        scanf("%d%d", &u, &v);
        for(int j = 1; j < 100; ++j){
            int idx = (u-1) * 100 + j;
            int idy = (v-1) * 100 + j + 1;
            for(int k = 1; k <= 50; ++k){
                add(idx, idy, 1, c + (k * k - (k-1) * (k-1))* d) ;
            }
        }
        for(int j = 1; j < 100; ++j){
            int idx = (v-1) * 100 + j;
            int idy = (u-1) * 100 + j + 1;
            for(int k = 1; k <= 50; ++k){
                add(idx, idy, 1, c + (k * k - (k-1) * (k-1))* d) ;
            }
        }
    }
    printf("%d\n", MaxFlow(s, t));
    return 0;
}


#include<algorithm>
#include<cstdio>
#include<queue>
#define Maxn 5500
#define Maxm 35500
#define INF 1000000000
using namespace std;
struct Line
{int nxt,t,c,l;}g[Maxm];
int fir[Maxn],tl=1;
void adl(int f,int t,int c,int cost){
  g[++tl]=(Line){fir[f],t,c,cost};fir[f]=tl;
  g[++tl]=(Line){fir[t],f,0,-cost};fir[t]=tl;
}
int S,T,pre[Maxn],lp[Maxn],flow[Maxn],dis[Maxn];
bool in[Maxn];
queue<int> q;
int spfa()
{
  for (int i=1;i<=T;i++)
    {dis[i]=INF;flow[i]=0;}
  flow[S]=INF;dis[S]=0;
  q.push(S);in[S]=1;
  while(!q.empty()){
    int u=q.front();
    in[u]=0;q.pop();
    for (int i=fir[u],v;i;i=g[i].nxt)
      if (g[i].c&&dis[v=g[i].t]>dis[u]+g[i].l){
        dis[v]=dis[u]+g[i].l;
        flow[v]=min(flow[u],g[i].c);
        lp[v]=i;pre[v]=u;
        if (!in[v]){in[v]=1;q.push(v);}
     }
  }return flow[T];
}
int n,m,k,C,D,pl[105][105],st[105][105];
struct Data
{int f,t;}s[105];
#define P(x,y) ((x)*n+(y))
int main()
{
  scanf("%d%d%d%d%d",&n,&m,&k,&C,&D);
  S=P(n+k,n)+1;T=S+2;
  adl(P(0,1),T,INF,0);
  for (int i=1,p;i<=k;i++){
    scanf("%d",&p);
    adl(S,P(0,p),1,0);
  }for (int i=1;i<=m;i++){
    scanf("%d%d",&s[i*2].f,&s[i*2].t);
    s[i*2-1]=(Data){s[i*2].t,s[i*2].f};
  }m*=2;
  for (int t=1;t<=n+k;t++){
    for (int i=1;i<=n;i++)
      adl(P(t-1,i),P(t,i),INF,0);
    for (int i=1;i<=m;i++){
      adl(P(t-1,s[i].f),P(t,s[i].t),1,D);
      pl[t][i]=tl;st[t][i]=1;
    }adl(P(t,1),T,INF,t*C);
  }
  int sav,cans=0;
  while(sav=spfa()){
    int u=T;
    while(u!=S){
      int las=pre[u];
      g[lp[u]].c-=sav;
      g[lp[u]^1].c+=sav;
      u=las;
    }cans+=dis[T]*sav;
    for (int t=1;t<=n+n;t++)
      for (int i=1;i<=m;i++)
        if (g[pl[t][i]].c){
          st[t][i]++;
          adl(P(t-1,s[i].f),P(t,s[i].t),1,D*(st[t][i]*2-1));
          pl[t][i]=tl;
        }
  }printf("%d\n",cans);
  return 0;
}


#include <bits/stdc++.h>
using namespace std;

//Start
typedef long long ll;
typedef double db;
#define mp(a,b) make_pair((a),(b))
#define x first
#define y second
#define bg begin()
#define ed end()
#define sz(a) int((a).size())
#define pb(a) push_back(a)
#define R(i,a,b) for(int i=(a),i##E=(b);i<i##E;i++)
#define L(i,a,b) for(int i=(b)-1,i##E=(a)-1;i>i##E;i--)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f;

//Data
const int N=50;
int n,m,k,c,d,mxt;

//Flows
const int fN=(N*3+1)*N+2;
int s,t,fn;
vector<int> e[fN],to,fw,co;
void adde(int u,int v,int w,int c){
    e[u].pb(sz(to)),to.pb(v),fw.pb(w),co.pb(+c);
    e[v].pb(sz(to)),to.pb(u),fw.pb(0),co.pb(-c);
}
int dep[fN],pre[fN]; bool vis[fN];
bool spfa(){
    fill(dep,dep+fn,iinf),fill(pre,pre+fn,-1),fill(vis,vis+fn,false);
    queue<int> q; q.push(s),vis[s]=true,dep[s]=0;
    while(sz(q)){
        int u=q.front(); q.pop(),vis[u]=false;
        for(int v:e[u])if(fw[v]&&dep[to[v]]>dep[u]+co[v])
            dep[to[v]]=dep[u]+co[v],pre[to[v]]=v,
            (!vis[to[v]])&&(q.push(to[v]),vis[to[v]]=true);
    }
    return dep[t]<iinf;
}
pair<int,int> mcmf(){
    pair<int,int> res(0,0);
    while(spfa()){
        int f=iinf;
        for(int u=t;u!=s;u=to[pre[u]^1]) f=min(f,fw[pre[u]]);
        for(int u=t;u!=s;u=to[pre[u]^1]) fw[pre[u]]-=f,fw[pre[u]^1]+=f;
        res.x+=f,res.y+=dep[t]*f;
    }
    return res;
}

//Main
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>n>>m>>k>>c>>d,mxt=N*3+1;
    fn=(t=(s=n*mxt)+1)+1;
    R(i,0,k){int u;cin>>u,--u,adde(s,u,1,0);}
    while(m--){
        int u,v; cin>>u>>v,--u,--v;
        R(i,0,mxt-1)R(p,1,k+1)
            adde(i*n+u,(i+1)*n+v,1,2*d*p-d),
            adde(i*n+v,(i+1)*n+u,1,2*d*p-d);
    }
    R(u,0,n)R(i,0,mxt-1) adde(i*n+u,(i+1)*n+u,k,0);
    R(i,0,mxt) adde(i*n,t,k,i*c);
    pair<int,int> ans=mcmf();
    assert(ans.x==k);
    cout<<ans.y<<'\n';
    return 0;
}


/*
ЗАПУСКАЕМ
░ГУСЯ░▄▀▀▀▄░РАБОТЯГУ░░
▄███▀░◐░░░▌░░░░░░░
░░░░▌░░░░░▐░░░░░░░
░░░░▐░░░░░▐░░░░░░░
░░░░▌░░░░░▐▄▄░░░░░
░░░░▌░░░░▄▀▒▒▀▀▀▀▄
░░░▐░░░░▐▒▒▒▒▒▒▒▒▀▀▄
░░░▐░░░░▐▄▒▒▒▒▒▒▒▒▒▒▀▄
░░░░▀▄░░░░▀▄▒▒▒▒▒▒▒▒▒▒▀▄
░░░░░░▀▄▄▄▄▄█▄▄▄▄▄▄▄▄▄▄▄▀▄
░░░░░░░░░░░▌▌░▌▌░░░░░
░░░░░░░░░░░▌▌░▌▌░░░░░
░░░░░░░░░▄▄▌▌▄▌▌░░░░░
 */
#include <iostream>
#include <complex>
#include <vector>
#include <string>
#include <algorithm>
#include <cstdio>
#include <numeric>
#include <cstring>
#include <ctime>
#include <cstdlib>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <list>
#include <cmath>
#include <bitset>
#include <cassert>
#include <queue>
#include <stack>
#include <deque>

using namespace std;
template<typename T1, typename T2>inline void chkmin(T1 &x, T2 y) { if (x > y) x = y; }
template<typename T1, typename T2>inline void chkmax(T1 &x, T2 y) { if (x < y) x = y; }
#define sz(c) (int)(c).size()
#define all(c) (c).begin(), (c).end()
#define rall(c) (c).rbegin(), (c).rend()
#define left left228
#define right right228
#define next next228
#define rank rank228
#define prev prev228
#define y1 y1228
#define read(FILENAME) freopen((FILENAME + ".in").c_str(), "r", stdin)
#define write(FILENAME) freopen((FILENAME + ".out").c_str(), "w", stdout)
#define files(FILENAME) read(FILENAME), write(FILENAME)
#define pb push_back
const string FILENAME = "input";
const int MAXN = 8200;
const long long INF = 1e14;

struct edge {
	int u, v;
	long long cap, flow;
	long long cost;
	long long rem() {
		return cap - flow;
	}
	edge(){}
	edge(int _u, int _v, long long _cap, long long _flow, long long _cost) {
		u = _u;
		v = _v;
		cap = _cap;
		flow = _flow;
		cost = _cost;
	}
};

int nodes;
vector<int> g[MAXN];
vector<edge> e;

void add_edge(int u, int v, long long cap, long long cost) {
	g[u].pb(sz(e));
	e.pb(edge(u, v, cap, 0, cost));
	g[v].pb(sz(e));
	e.pb(edge(v, u, 0, 0, -cost));
}

long long dist[MAXN], mncost;
int pre[MAXN];
long long cap[MAXN], mxflow;
bool inq[MAXN];

void flow(int s, int t) {
	memset(inq, 0, sizeof(inq));
	mxflow = mncost = 0;
	while (true) {
		fill(dist, dist + nodes, INF);
		dist[s] = 0;
		memset(pre, -1, sizeof(pre));
		pre[s] = 0;
		memset(cap, 0, sizeof(cap));
		cap[s] = INF;
		queue<int> q;
		q.push(s);
		inq[s]=1;
		while (!q.empty()) {
			int u = q.front();
			q.pop();
			inq[u] = 0;
			for (int it = 0; it < sz(g[u]); it++) {
				int i = g[u][it];
				edge &f = e[i];
				if (f.rem() && dist[f.v] > dist[u] + f.cost + 1e-9) {
					dist[f.v] = dist[u] + f.cost;
					pre[f.v] = i;
					cap[f.v] = min(cap[u], f.rem());
					if (!inq[f.v]) {
						q.push(f.v);
						inq[f.v] = 1;
					}
				}
			}
		}
		if (pre[t] < 0) {
			break;
		}
		mxflow +=cap[t];
		mncost += cap[t] * dist[t];
		int v = t;
		while (v != s) {
			e[pre[v]].flow += cap[t];
			e[pre[v] ^ 1].flow -= cap[t];
			v = e[pre[v]].u;
		}
	}
}

int n, m, k, c, d;

int main(){
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	//read(FILENAME);
	cin >> n >> m >> k >> c >> d;
	for (int i = 0; i < k; i++) {
		int x;
		cin >> x;
		x--;
		add_edge(0, x + 1, 1, 0);
	}
	for (int i = 0; i < m; i++) {
		int x, y;
		cin >> x >> y;
		x--, y--;
		for (int i = 0; i < 105; i++) {
			for (int j = 0; j < 51; j++) {
				add_edge(i * n + x + 1, (i + 1) * n + y + 1, 1, c + d * (2 * j + 1));
				add_edge(i * n + y + 1, (i + 1) * n + x + 1, 1, c + d * (2 * j + 1));
			}
		}
	}
	for (int i = 0; i < 105; i++) {
		for (int j = 0; j < n; j++) {
			add_edge(i * n + j + 1, (i + 1) * n + j + 1, 51, c);
		}
	}
	for (int i = 0; i < 105; i++) {
		add_edge(i * n + 1, 105 * n + 1, 51, 0);
	}
	nodes = 6 + 107 * n;
	flow(0, 105 * n + 1);
	cout << mncost << '\n';
	return 0;
}


#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
using i64=int_least64_t;

namespace std
{
    // hash
    template <class T> size_t hash_combine(size_t seed, T const &key) { return seed ^ (hash<T>()(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); }
    template <class T, class U> struct hash<pair<T, U>> { size_t operator()(pair<T, U> const &pr) const { return hash_combine(hash_combine(0, pr.first), pr.second); } };
    template <class tuple_t, size_t index = tuple_size<tuple_t>::value - 1> struct tuple_hash_calc { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(tuple_hash_calc<tuple_t, index - 1>::apply(seed, t), get<index>(t)); } };
    template <class tuple_t> struct tuple_hash_calc<tuple_t, 0> { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(seed, get<0>(t)); } };
    template <class... T> struct hash<tuple<T...>> { size_t operator()(tuple<T...> const &t) const { return tuple_hash_calc<tuple<T...>>::apply(0, t); } };
    // iostream
    template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) { return is >> p.first >> p.second; }
    template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << p.first << ' ' << p.second; }
    template <class tuple_t, size_t index> struct tupleis { static istream &apply(istream &is, tuple_t &t) { tupleis<tuple_t, index - 1>::apply(is, t); return is >> get<index>(t); } };
    template <class tuple_t> struct tupleis<tuple_t, SIZE_MAX> { static istream &apply(istream &is, tuple_t &t) { return is; } };
    template <class... T> istream &operator>>(istream &is, tuple<T...> &t) { return tupleis<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(is, t); }
    template <> istream &operator>>(istream &is, tuple<> &t) { return is; }
    template <class tuple_t, size_t index> struct tupleos { static ostream &apply(ostream &os, const tuple_t &t) { tupleos<tuple_t, index - 1>::apply(os, t); return os << ' ' << get<index>(t); } };
    template <class tuple_t> struct tupleos<tuple_t, 0> { static ostream &apply(ostream &os, const tuple_t &t) { return os << get<0>(t); } };
    template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t) { return tupleos<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os, t); }
    template <> ostream &operator<<(ostream &os, const tuple<> &t) { return os; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    istream& operator>>(istream& is, Container &cont) { for(auto&& e : cont) is >> e; return is; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    ostream& operator<<(ostream& os, const Container &cont) { bool flag = 1; for(auto&& e : cont) flag ? flag = 0 : (os << ' ', 0), os << e; return os; }
} // namespace std

#include <cassert>
#include <list>
#include <vector>

// Base class of flow algorithms
template <class cap_t, class cost_t>
struct flow_base
{
    struct edge_t
    {
        size_t src, dst;
        cap_t cap; cost_t cost;
        edge_t *rev;
        edge_t(size_t _src, size_t _dst, cap_t _cap, cost_t _cost, edge_t *_rev)
            : src(_src), dst(_dst), cap(_cap), cost(_cost), rev(_rev) {}
    }; // struct edge_t

protected:
    using adj_type = std::vector<std::list<edge_t>>;
    adj_type adj;

public:
    flow_base(size_t _n = 0) : adj(_n) {}

    flow_base(const flow_base& other) : adj(other.size())
    {
        for(size_t node{0}; node != other.size(); ++node)
        {
            for(const auto &e : other[node])
            {
                if(e.src == node)
                {
                    adj[e.src].emplace_back(e);
                    adj[e.dst].emplace_back(*e.rev);
                    adj[e.src].back().rev = &adj[e.dst].back();
                    adj[e.dst].back().rev = &adj[e.src].back();
                    e.rev->src = -1;
                }
                else
                {
                    e.rev->rev->src = node;
                }
            }
        }
    }

    flow_base &operator=(const flow_base &other)
    {
        if(this != &other)
        {
            flow_base cop(other);
            std::swap(adj, cop.adj);
        }
        return *this;
    }

    size_t size() const { return adj.size(); }

    typename decltype(adj)::reference operator[](size_t node) { assert(node < size()); return adj[node]; }
    typename decltype(adj)::const_reference operator[](size_t node) const { assert(node < size()); return adj[node]; }

    void add_edge(size_t src, size_t dst, cap_t cap, cost_t cost)
    {
        assert(src < size()); assert(dst < size());
        if(cap <= 0) return;
        adj[src].emplace_back(src, dst, cap, cost, nullptr);
        adj[dst].emplace_back(dst, src, 0, -cost, nullptr);
        adj[src].back().rev = &adj[dst].back();
        adj[dst].back().rev = &adj[src].back();
    }
}; // struct flow_base

template <class cap_t, class cost_t>
class min_cost_flow : public flow_base<cap_t, cost_t>
{
    using base = flow_base<cap_t, cost_t>;
    using edge_t = typename base::edge_t;

    template <class type>
    constexpr bool valid(const type &val) const { return val != static_cast<type>(-1); }

    template <class type>
    constexpr void make_invalid(type &val) const { val = -1; }

    cost_t min_cost, total_cost;
    std::vector<cap_t> supp;
    std::vector<cost_t> ptnl;

    void copy_member(const min_cost_flow &other)
    {
        min_cost = other.min_cost;
        total_cost = other.total_cost;
        supp = other.supp;
        ptnl = other.ptnl;
    }

    void Dijkstra(std::vector<edge_t*> &last)
    {
        const cost_t infty(total_cost + 1);
        std::vector<cost_t> dist(base::size(), infty);
        //*/ // O((V + E)logV)
        std::priority_queue<std::pair<cost_t, size_t>> que;
        for(size_t node{}; node != base::size(); ++node)
        {
            if(supp[node] > static_cast<cap_t>(0))
            {
                dist[node] = 0;
                que.emplace(0, node);
            }
        }
        while(!que.empty())
        {
            // auto [nsp, node] = que.top();
            cost_t nsp; size_t node;
            std::tie(nsp, node) = que.top();
            que.pop();
            if(-nsp != dist[node]) continue;
            ptnl[node] -= nsp;
            if(ptnl[node] > infty) ptnl[node] = infty;
            make_invalid(dist[node]);
            for(edge_t &e : base::adj[node])
            {
                if(!valid(dist[e.dst]) || e.cap == static_cast<cap_t>(0)) continue;
                if(dist[e.dst] + ptnl[e.dst] > ptnl[node] + e.cost)
                {
                    dist[e.dst] = ptnl[node] + e.cost - ptnl[e.dst];
                    last[e.dst] = &e;
                    que.emplace(-dist[e.dst], e.dst);
                }
            }
        }
        /*/ // O(V^2)
        //*/
    }

public:
    min_cost_flow(size_t _n = 0) : base::flow_base(_n), min_cost(0), total_cost(0), supp(_n), ptnl(_n)  {}

    min_cost_flow(const min_cost_flow &other) : base::flow_base(other)
    {
        copy_member(other);
    }

    min_cost_flow &operator=(const min_cost_flow &other)
    {
        base::operator=(other);
        copy_member(other);
        return *this;
    }

    void add_edge(size_t src, size_t dst, cap_t cap, cost_t cost)
    {
        assert(src != dst);
        if(cap <= static_cast<cap_t>(0)) return;
        if(cost < static_cast<cost_t>(0))
        {
            supp[src] -= cap;
            supp[dst] += cap;
            min_cost += cap * cost;
            total_cost -= cap * cost;
            base::add_edge(dst, src, cap, -cost);
        }
        else
        {
            total_cost += cap * cost;
            base::add_edge(src, dst, cap, cost);
        }
    }

    void supply(size_t node, cap_t vol) { supp[node] += vol; }

    bool flow()
    {
        for(bool aug = true; aug; )
        {
            aug = false;
            std::vector<edge_t*> last(base::size());
            Dijkstra(last);
            std::vector<bool> shut(base::size());
            for(size_t dst{}; dst != base::size(); ++dst)
            {
                if(supp[dst] < static_cast<cap_t>(0) and last[dst])
                {
                    cap_t resid{-supp[dst]};
                    size_t src{dst}, block;
                    make_invalid(block);
                    while(last[src] && !shut[src])
                    {
                        if(resid >= last[src]->cap) resid = last[block = src]->cap;
                        src = last[src]->src;
                    }
                    if(shut[src]) block = src;
                    else
                    {
                        if(resid >= supp[src])
                        {
                            resid = supp[src];
                            block = src;
                        }
                        for(size_t node{dst}; node != src; node = last[node]->src)
                        {
                            last[node]->cap -= resid;
                            last[node]->rev->cap += resid;
                        }
                        supp[src] -= resid;
                        supp[dst] += resid;
                        min_cost += ptnl[dst] * resid;
                        aug = true;
                    }
                    if(valid(block))
                    {
                        for(size_t node{dst}; node != block; node = last[node]->src) shut[node] = true;
                        shut[block]=true;
                    }
                }
            }
        }
        for(cap_t s : supp) if(s > static_cast<cap_t>(0)) return false;
        return true;
    }

    cost_t optimal() { assert(flow()); return min_cost; }
};

main()
{
    min_cost_flow<int,i64> mcf(6100);
    int n,m,k,c,d; cin>>n>>m>>k>>c>>d;
    const int tlim=105;
    for(int i=0; i<k; ++i)
    {
        int j; cin>>j; j--;
        mcf.supply(j,1);
    }
    for(int i=0; i<m; ++i)
    {
        int u,v; cin>>u>>v; --u,--v;
        for(int t=0; t<tlim; ++t)
        {
            int nu=u+n;
            int nv=v+n;
            for(int x=0; x<k; ++x)
            {
                mcf.add_edge(u,nv,1,c+d*(x*2+1));
                mcf.add_edge(v,nu,1,c+d*(x*2+1));
            }
            u=nu;
            v=nv;
        }
    }
    for(int i=1; i<n; ++i)
    {
        for(int t=0; t<tlim; t++)
        {
            mcf.add_edge(n*t+i,n*(t+1)+i,k,c);
        }
    }
    const int dst=mcf.size()-1;
    mcf.supply(dst,-k);
    for(int t=0; t<=tlim; ++t) mcf.add_edge(t*n,dst,k,0);
    cout << mcf.optimal() << "\n";
}


#include<bits/stdc++.h>

using namespace std;

struct edge
{
	int y, c, f, cost;
	edge() {};
	edge(int y, int c, int f, int cost) : y(y), c(c), f(f), cost(cost) {};
};

vector<edge> e;

const int N = 14043;
vector<int> g[N];

long long ans = 0;
long long d[N];
int p[N];
int pe[N];
int inq[N];

const long long INF64 = (long long)(1e18);

int s = N - 2;
int t = N - 1;

int rem(int x)
{
	return e[x].c - e[x].f;
}

void push_flow()
{
	for(int i = 0; i < N; i++) d[i] = INF64, p[i] = -1, pe[i] = -1, inq[i] = 0;
	d[s] = 0;
	queue<int> q;
	q.push(s);
	inq[s] = 1;
	while(!q.empty())
	{
		int k = q.front();
		q.pop();
		inq[k] = 0;
		for(auto x : g[k])
		{
			if(!rem(x)) continue;
			int c = e[x].cost;
			int y = e[x].y;
			if(d[y] > d[k] + c)
			{
				d[y] = d[k] + c;
				p[y] = k;
				pe[y] = x;
				if(inq[y] == 0)
				{
					inq[y] = 1;
					q.push(y);
				}
			}
		}
	}
	int cur = t;
//	vector<int> zz(1, cur);
	while(cur != s)
	{
		e[pe[cur]].f++;
		e[pe[cur] ^ 1].f--;
		cur = p[cur];
//		zz.push_back(cur);
	}
//	reverse(zz.begin(), zz.end());
//	for(auto x : zz) cerr << x << " ";
//	cerr << endl;
	ans += d[t];
}

void add_edge(int x, int y, int c, int cost)
{
	g[x].push_back(e.size());
	e.push_back(edge(y, c, 0, cost));
	g[y].push_back(e.size());
	e.push_back(edge(x, 0, 0, -cost));
}

int main()
{
	int n, m, k, c, d;
	cin >> n >> m >> k >> c >> d;
	for(int i = 0; i < k; i++)
	{
		int x;
		cin >> x;
		--x;
		add_edge(s, x, 1, 0);
	}
	int tt = 101;
	for(int i = 0; i < tt; i++)
		add_edge(0 + i * n, t, k, i * c);
	for(int i = 0; i < m; i++)
	{
		int x, y;
		cin >> x >> y;
		--x;
		--y;
		for(int i = 0; i < tt - 1; i++)
			for(int j = 0; j < k; j++)
				add_edge(x + i * n, y + i * n + n, 1, d * (j * 2 + 1));
		for(int i = 0; i < tt - 1; i++)
			for(int j = 0; j < k; j++)
				add_edge(y + i * n, x + i * n + n, 1, d * (j * 2 + 1));
 	}
 	for(int i = 0; i < n; i++)
 		for(int j = 0; j < tt - 1; j++)
 			add_edge(i + j * n, i + j * n + n, k, 0);
 	for(int i = 0; i < k; i++)
 		push_flow();
 	cout << ans << endl;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
#define ull unsigned long long
#define mp make_pair
const int maxn=5e3+5;
const ll inf=1e9+7;

inline int read() {
    int X = 0,w = 0; char ch = 0;
    while(!isdigit(ch)) {w |= ch == '-';ch = getchar();}
    while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48),ch=getchar();
    return w ? -X : X;
}
struct edge
{
    int from,to,cap,flow,cost;
    edge(int a,int b,int c,int d,int e)
    {
        from = a,to = b,cap = c,flow = d,cost = e;
    }
};

ll n,m;
int a[maxn];
int startPoint,endPoint;

struct MCMF
{
    int n, m;
    vector<edge>e;
    vector<int>g[maxn];
    int inq[maxn];
    int d[maxn];
    int p[maxn];
    int a[maxn];
    void Init(int n)
    {
        this -> n = n;
        for(int i = 0;i <= n; i++)
            g[i].clear();
        e.clear();
    }
    void add(int from,int to,int cap,int cost)
    {
        e.push_back(edge(from,to,cap,0,cost));
        e.push_back(edge(to,from,0,0,-cost));
        m = e.size();
        g[from].push_back(m-2);
        g[to].push_back(m-1);
    }
    bool bellman(int s,int t,int& flow,int& cost)
    {
        for(int i = 0;i <= t; i++)
            d[i] = inf,inq[i] = 0;
        d[s] = 0;inq[s] = 1;p[s] = 0;a[s] = inf;
        queue<int>Q;
        Q.push(s);
        while(!Q.empty())
        {
            int u = Q.front();

            Q.pop();
            inq[u] = 0;

            for(int i = 0;i < g[u].size(); i++)
            {
                edge& ee = e[g[u][i]];

                //cout<<ee.cap<<"  "<<ee.flow<<"  "<<d[ee.to]<<"  "<<d[u]<<"  "<<ee.cost<<endl;
                if(ee.cap > ee.flow && d[ee.to] > d[u] + ee.cost)
                {
                    //cout<<"zzzz"<<endl;
                    d[ee.to] = d[u] + ee.cost;
                    p[ee.to] = g[u][i];
                    a[ee.to] = min(a[u],ee.cap - ee.flow);
                    if(!inq[ee.to])
                    {
                        Q.push(ee.to);
                        //cout<<"in="<<ee.to<<endl;
                        inq[ee.to] = 1;
                    }
                }
            }
        }

        //cout<<"hahaha"<<endl;
        if(d[t] == inf)
            return false;
        flow += a[t];
        cost += d[t] * a[t];
        int u = t;
        while(u != s){
            e[p[u]].flow += a[t];
            e[p[u]^1].flow -= a[t];
            u = e[p[u]].from;
        }

        return true;
    }
    int minCost(int s,int t)
    {
        int flow = 0,cost = 0;
        while(bellman(s,t,flow,cost));
        return cost;
    }
}solve;

int main(){
    int k,c,d;
    cin>>n>>m>>k>>c>>d;

    for(int i=1;i<=k;i++){
        scanf("%d",&a[i]);
    }

    startPoint=0,endPoint=n*100+1;

    for(int i=1;i<=k;i++){
        solve.add(startPoint,1+(a[i]-1)*100,1,0);
    }

    for(int i=1;i<=n;i++){
        for(int j=1;j<100;j++){
            int p=(i-1)*100LL;
            solve.add(p+j,p+j+1,inf,c);
        }
    }

    for(int i=1;i<=100;i++)solve.add(i,endPoint,inf,0);

    while(m--){
        int x,y;
        scanf("%d%d",&x,&y);
        for(int i=1;i<100;i++){
            int p=(x-1)*100+i;
            int pp=(y-1)*100+i+1;
            for(int j=1;j<=50;j++){
                solve.add(p,pp,1,d*(j*j-(j-1)*(j-1))+c);
            }
        }

        for(int i=1;i<100;i++){
            int p=(y-1)*100+i;
            int pp=(x-1)*100+i+1;
            for(int j=1;j<=50;j++){
                solve.add(p,pp,1,d*(j*j-(j-1)*(j-1))+c);
            }
        }

    }

    printf("%d\n",solve.minCost(startPoint,endPoint));
    return 0;

}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn=6000;
const int inf=INT_MAX;
const ll inff=1e18;
const ll mod=1e9+7;
#define pii pair<int,int>
#define mkp make_pair
#define F first
#define S second
#define pb push_back
#define sz(v) ((int)(v).size())
#define all(v) (v).begin(),(v).end()
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define int ll
//#define endl '\n'

int n,s,t;
struct edge
{
    int to,cap,cost,rev;
};
vector<edge> G[maxn];
int dist[maxn];
int prevv[maxn],preve[maxn];
int inq[maxn];

void init(int _n,int _s,int _t)
{
    for (int i=0;i<=_n;i++) G[i].clear();
    n=_n;
    s=_s;
    t=_t;
}

void add_edge(int from,int to,int cap,int cost)
{
    G[from].pb({to,cap,cost,sz(G[to])});
    G[to].pb({from,0,-cost,sz(G[from])-1});
}

int min_cost_flow(int f)
{
    int res=0;
    while (f>0)
    {
        fill(dist,dist+n,inff);
        dist[s]=0;
        queue<int> q;
        q.push(s);
        inq[s]=1;
        while (!q.empty())
        {
            int now=q.front();
            q.pop();
            inq[now]=0;
            for (int i=0;i<sz(G[now]);i++)
            {
                edge &e=G[now][i];
                if (e.cap>0&&dist[now]+e.cost<dist[e.to])
                {
                    dist[e.to]=dist[now]+e.cost;
                    prevv[e.to]=now;
                    preve[e.to]=i;
                    if (!inq[e.to]) inq[e.to]=1,q.push(e.to);
                }
            }
        }

        if (dist[t]==inff) return -1;

        int d=f;
        for (int v=t;v!=s;v=prevv[v])
        {
            d=min(d,G[prevv[v]][preve[v]].cap);
        }
        f-=d;
        res+=d*dist[t];
        for (int v=t;v!=s;v=prevv[v])
        {
            edge &e=G[prevv[v]][preve[v]];
            e.cap-=d;
            G[v][e.rev].cap+=d;
        }
    }
    return res;
}

int N,M,K,C,D,X,Y;
int A[58];
vector<int> H[57];

int32_t main()
{
    IOS
    cin>>N>>M>>K>>C>>D;
    for (int i=1;i<=K;i++)
    {
        cin>>X;
        A[X]++;
    }
    for (int i=1;i<=M;i++)
    {
        cin>>X>>Y;
        H[X].pb(Y);
        H[Y].pb(X);
    }

    init(5103,0,5101);
    for (int i=2;i<=N;i++) add_edge(0,i,A[i],0);
    for (int i=0;i<=100;i++)
    {
        for (int l=1;l<=N;l++)
        {
            add_edge(50*i+l,50*(i+1)+l,K,0);
            for (int j:H[l])
            {
                for (int k=1;k<=K;k++)
                {
                    add_edge(50*i+l,50*(i+1)+j,1,D*(2*k-1));
                }
            }
        }
    }
    for (int i=1;i<=101;i++) add_edge(50*i+1,5101,K,C*i);
    cout<<min_cost_flow(K)<<endl;
}


#include <bits/stdc++.h>
using namespace std;
#define _USE_MATH_DEFINES

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

// DON'T USE THESE MACROS DURING ICPC PRACTICE
#define For(i,n) for (int i=0; i<n; i++)
#define FOR(i,a,b) for (int i=a; i<=b; i++)
#define Down(i,n) for (int i=n-1; i>=0; i--)
#define DOWN(i,a,b) for (int i=b; i>=a; i--)

typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
typedef complex<ld> pt;
typedef vector<pt> pol;
typedef vector<int> vi;

const char nl = '\n';
const ll INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const ll MOD = 1e9+7;
const ld EPS = 1e-10;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());

const int T = 99;
const int C = 15;
namespace Flow {
	const int N = 50*T + 2;
	const int M = 2*N*C + N + 7;
	// data structures and helper functions common to all flow routines
	int par[N], first[N], nxt[2*M], ep[2*M], m;
	ll flo[2*M], cap[2*M], cost[2*M];
	void init() { m = 0; memset(first,-1,sizeof first); memset(flo,0,sizeof flo); }
	void add_edge(int a, int b, ll c=1, ll p=0) { //a,b - nodes, c, p - cap, price
		nxt[m] = first[ep[m]=a], first[ep[m]] = m, cap[m] = c, cost[m] =  p, ++m;
		nxt[m] = first[ep[m]=b], first[ep[m]] = m, cap[m] = 0, cost[m] = -p, ++m; }
	// Minimum cost maximum flow, assuming there are no negative cost cycles
	// USAGE: 1) init(); 2) add edges, 3) mcf_pot_init(numV) and 4)
	// ll price=0,flow=0; while (ll df = mcf_update(s, t, price, numV)) flow += df;
	//! for sparse graphs, may help to change Dijkstra from O(N^2) to O(M*lgN)
	int q[N], inq[N];
#define BUBL { \
	t = q[i]; q[i] = q[j]; q[j] = t; \
	t = inq[q[i]]; inq[q[i]] = inq[q[j]]; inq[q[j]] = t; }
	bool vis[N]; ll pot[N], dist[N];
	void mcf_pot_init(int n) { memset(pot, 0, sizeof pot);
		// if all edge costs >= 0, we can safely return before the Bellman-Ford here
		for (int k = 1; k < n; ++k) for (int e = 0; e < m; ++e)
			if (cap[e]) pot[ep[e^1]] = min(pot[ep[e^1]], pot[ep[e]] + cost[e]); }
	ll mcf_update(int s, int t, ll& price, int n) {
		memset(vis, 0, sizeof vis); memset(dist, INF, sizeof dist); dist[s] = 0;
		memset(inq, -1, sizeof inq);
		int qs = 0; inq[q[qs++] = s] = 0;
		while (qs) {
			int u = q[0]; inq[u] = -1;
			q[0] = q[--qs];
			if( qs ) inq[q[0]] = 0;
			for( int i = 0, j = 2*i + 1, t; j < qs; i = j, j = 2*i + 1 ) {
				if( j + 1 < qs && dist[q[j + 1]] < dist[q[j]] ) j++;
				if( dist[q[j]] >= dist[q[i]] ) break;
				BUBL; }
			if (vis[u] == 1) continue; vis[u] = 1;
			for (int e = first[u]; e != -1; e = nxt[e]) { int v = ep[e^1];
				if (flo[e] < cap[e] && dist[v] > dist[u] + pot[u] - pot[v] + cost[e]) {
					dist[v] = dist[u] + pot[u] - pot[v] + cost[e], par[v] = e;
					if( inq[v] < 0 ) { inq[q[qs] = v] = qs; qs++; }
					for( int i = inq[v], j = ( i - 1 )/2, t;
							dist[q[i]] < dist[q[j]]; i = j, j = ( i - 1 )/2 )
						BUBL;
				}
			}
		}
		if (dist[t] >= INF) return 0; ll df = INF;
		for (int e, i = t; i != s; i = ep[e])
			e = par[i], df = min(df, cap[e] - flo[e]);
		for (int e, i = t; i != s; i = ep[e])
			e = par[i], flo[e] += df, flo[e^1] -= df, price += df*cost[e];
		for (int i = 0; i < n; ++i) pot[i] = min(INF, dist[i] + pot[i]);
		return df; }
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cout << fixed << setprecision(10);

	int n,m,k,c,d;
	cin>>n>>m>>k>>c>>d;

	const int source = 0;
	const int sink = n*T+1;
	Flow::init();

	for(int i=0;i<k;i++) {
		int a;
		cin>>a;
		Flow::add_edge(source, a, 1, 0);
	}
	for(int t=0;t<T;t++) {
		Flow::add_edge(1+t*n, sink, INF, 0);
		if(t>0) {
			for(int i=1;i<=n;i++) {
				Flow::add_edge(i+(t-1)*n, i+t*n, INF, c);
			}
		}
	}

	for(int i=0;i<m;i++) {
		int a, b;
		cin >> a >> b;
		for(int j=0;j<C;j++) {
			int cost = (j+1)*(j+1) - j*j;
			for(int t=1;t<T;t++) {
				Flow::add_edge(a+(t-1)*n, b+t*n, 1, cost*d + c);
				Flow::add_edge(b+(t-1)*n, a+t*n, 1, cost*d + c);
			}
		}
	}

	Flow::mcf_pot_init(Flow::N);
	ll price = 0;
	ll flow = 0;
	while (ll df = Flow::mcf_update(source, sink, price, Flow::N)) flow += df;
	assert(flow==k);
	cout << price << nl;

	return 0;
}


#include <bits/stdc++.h>
#define fi first
#define se second
using namespace std;

const int MX = 5500;
const long long INF = 1E9 + 7;

int n, m, k, c, d;
int u, v, mx, s = MX - 2, t = MX - 1, mf = 0, tr[MX];
long long ans = 0, dis[MX];
priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> pq;

struct SEdge
{
    int v, c;
    int ind, cap;
};
vector<SEdge> adj[MX];

void add_edge(int u, int v, int c, int cap)
{
    int s1 = adj[u].size(), s2 = adj[v].size();
    adj[u].push_back((SEdge){v, c, s2, cap});
    adj[v].push_back((SEdge){u, -c, s1, 0});
}

void dijkstra()
{
    fill(dis, dis + MX, INF);
    pq.push({dis[s] = 0, s});
    while (!pq.empty())
    {
        pair<long long, int> u = pq.top();
        pq.pop();
        if (u.fi > dis[u.se])
            continue;
        for (SEdge &ed : adj[u.se])
        {
            if (ed.cap > 0 && dis[ed.v] > u.fi + ed.c)
            {
                tr[ed.v] = ed.ind;
                pq.push({dis[ed.v] = u.fi + ed.c, ed.v});
            }
        }
    }
}

void trace()
{
    int mx = k, v = t;
    while (v != s)
    {
        int u = adj[v][tr[v]].v, ind = adj[v][tr[v]].ind;
        mx = min(mx, adj[u][ind].cap);
        v = u;
    }
    mf += mx; ans += mx * dis[t];
    v = t;
    while (v != s)
    {
        int u = adj[v][tr[v]].v, ind = adj[v][tr[v]].ind;
        adj[v][tr[v]].cap += mx;
        adj[u][ind].cap -= mx;
        v = u;
    }
}

int at(int u, int t)
{
    return u + t * n;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> n >> m >> k >> c >> d;
    mx = n + k;
    for (int i = 0; i < k; i++)
    {
        cin >> u;
        add_edge(s, at(u, 0), 0, 1);
    }
    for (int i = 0; i <= mx; i++)
        add_edge(at(1, i), t, c * i, k);
    for (int i = 1; i <= n; i++)
        for (int j = 0; j < mx; j++)
            add_edge(at(i, j), at(i, j + 1), 0, k);
    while (m--)
    {
        cin >> u >> v;
        for (int i = 1; i <= k; i++)
            for (int j = 0; j < mx; j++)
            {
                add_edge(at(u, j), at(v, j + 1), d * (2 * i - 1), 1);
                add_edge(at(v, j), at(u, j + 1), d * (2 * i - 1), 1);
            }
    }
    while (mf < k)
    {
        dijkstra();
        trace();
    }
    cout << ans;
}


#include <bits/stdc++.h>
using namespace std;
#define maxn 15000
struct Edge{
    int to,cap,flow,cost;
};
vector<Edge> e;
vector<int> head[maxn];
long long ans,dis[maxn];
int n,m,k,c,d,p[maxn],pe[maxn],inq[maxn],s=9998,t=9999,cur,i,j;
void add_edge(int x, int y, int c, int cost) {
	head[x].push_back(e.size()),e.push_back(Edge{y, c, 0, cost});
	head[y].push_back(e.size()),e.push_back(Edge{x, 0, 0, -cost});
}
void push_rebel() {
    fill(dis,dis+10000,(long long)1e18),fill(p,p+10000,-1),fill(pe,pe+10000,-1),fill(inq,inq+10000,0);
    dis[s] = 0;
    queue<int> q;
    q.push(s),inq[s] = 1,cur = t;
    while(!q.empty()){
        int k = q.front();q.pop();
        inq[k] = 0;
        for(auto x: head[k]) {
            if(!(e[x].cap - e[x].flow)) continue;
            int c = e[x].cost,y = e[x].to;
            if(dis[y]>dis[k]+c) {
                dis[y] = dis[k] + c,p[y] = k,pe[y] = x;
                if(!inq[y]) inq[y] = 1,q.push(y);
            }
        }
    }
	while(cur != s) {
		e[pe[cur]].flow++;
		e[pe[cur] ^ 1].flow--;
		cur = p[cur];
    }
	ans += dis[t];
}
int main() {
    cin >> n >> m >> k >> c >> d;
    int x,y;
    for(int i = 1; i<=k;i++) { cin >> x;x--;add_edge(s,x,1,0);}
    for(int i = 1; i<=101;i++) add_edge((i-1)*n,t,k,(i-1)*c);
    for(int i = 1; i<=m; i++){
		cin >> x >> y;x--,y--;
		for(int i = 1; i<=100; i++) for(int j = 1; j<=k; j++)
			add_edge(x+(i-1)*n,y+(i-1)*n+n,1,d*((j-1)*2+1)),add_edge(y+(i-1)*n,x+(i-1)*n+n,1,d*((j-1)*2+1));
 	}
 	for(int i = 1; i<=n; i++) for(int j = 1; j<=100; j++) add_edge(i-1+(j-1)*n,i-1+(j-1)*n+n,k,0);
    for(int i = 1;i<=k;i++) push_rebel();
    cout << ans << endl;
    return 0;
}


#include <bits/stdc++.h>
#define rep(i,n) for (int i = 0; i < n; i++)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pi;
typedef pair<pi, pi> pp;
typedef pair<ll, ll> pl;
const double EPS = 1e-9;
const ll MOD = 1000000007;
const int inf = 1 << 30;
const ll linf = 1LL << 60;

struct edge{int to, cap, cost, rev; };

struct MIN_COST_FLOW {
    #define MAX_V 5010
    int V;
    vector<edge> G[MAX_V];
    int h[MAX_V];
    int dist[MAX_V];
    int prevv[MAX_V], preve[MAX_V];

    void init (int n) {
        V = n;
    }

    void add_edge(int from, int to, int cap, int cost){
        //cerr << from << " " << to << " " << cap << " " << cost << endl;
        G[from].push_back((edge){to, cap, cost, (int)G[to].size()});
        G[to].push_back((edge){from, 0, -cost, (int)G[from].size()-1});
    }

    int min_cost_flow(int s, int t, int f){
        int res = 0;
        fill(h, h+V, 0);
        while(f > 0){
            priority_queue<pi, vector<pi>, greater<pi> > que;
            fill(dist, dist+V, inf);
            dist[s] = 0;
            que.push(pi(0,s));
            while(!que.empty()){
                pi p = que.top(); que.pop();
                int v = p.second;
                if(dist[v] < p.first) continue;
                for(int i = 0; i < G[v].size(); i++){
                    edge &e = G[v][i];
                    if(e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]){
                        dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
                        prevv[e.to] = v;
                        preve[e.to] = i;
                        que.push(pi(dist[e.to],e.to));
                    }
                }
            }
            if(dist[t] == inf){
                return -1;
            }
            for(int v = 0; v < V; v++) h[v] += dist[v];

            int d = f;
            for(int v = t; v != s; v = prevv[v]){
                d = min(d, G[prevv[v]][preve[v]].cap);
            }
            f -= d;
            res += d*h[t];
            for(int v = t; v != s; v = prevv[v]){
                edge &e = G[prevv[v]][preve[v]];
                e.cap -= d;
                G[v][e.rev].cap += d;
            }
        }
        return res;
    }
};

MIN_COST_FLOW mcf;

int n, m, k, c, d;
int a[50];
int cnt[50];
vector<int> e[50];

const int T = 100;

int main() {
    scanf("%d%d%d%d%d", &n, &m, &k, &c, &d);
    rep(i,k) scanf("%d", a+i);
    rep(i,k) cnt[a[i]-1]++;
    rep(i,m) {
        int x, y; scanf("%d%d", &x, &y);
        x--; y--;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    mcf.init(n*T+2);
    rep(i,n) mcf.add_edge(n*T, i, cnt[i], 0);
    rep(i,T) mcf.add_edge(i*n, n*T+1, k, c*i);
    rep(i,n) {
        rep(j,T-1) mcf.add_edge(j*n+i, (j+1)*n+i, k, 0);
        for (int to: e[i]) {
            rep(j,T-1) {
                rep(u,k) {
                    int cost = (u+1)*(u+1)*d-u*u*d;
                    mcf.add_edge(j*n+i, (j+1)*n+to, 1, cost);
                }
            }
        }
    }
    printf("%d\n", mcf.min_cost_flow(n*T, n*T+1, k));
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

const int N=10005,S=N-2,T=N-1;
const int M=2e6+10;
const int inf=2e9;

int head[N],to[M],nxt[M],w[M],c[M],cnt=1;

inline void addedge(int x, int y, int flow, int cost){
	to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
	w[cnt]=flow,c[cnt]=cost;
	to[++cnt]=x,nxt[cnt]=head[y],head[y]=cnt;
	w[cnt]=0,c[cnt]=-cost;
}

queue <int> q;
long long dis[N];
bool mark[N];

inline bool spfa(){
	memset(mark,0,sizeof(mark));
	memset(dis,0x3f,sizeof(dis));
	q.push(T); dis[T]=0; mark[T]=1;
	while (!q.empty()){
		int x=q.front();
		mark[x]=0; q.pop();
		for (int i=head[x];i;i=nxt[i]){
			int y=to[i];
			if (w[i^1]&&dis[y]>dis[x]+c[i^1]){
				dis[y]=dis[x]+c[i^1];
				if (!mark[y]){
					q.push(y); mark[y]=1;
				}
			}
		}
	}
	return dis[S]<1e18;
}

inline int dfs(int x, int lim, ll &cost){
	int flow=0; mark[x]=1;
	if (x==T) return lim;
	for (int i=head[x];i;i=nxt[i]){
		int y=to[i];
		if (!w[i]||mark[y]) continue;
		if (dis[x]!=dis[y]+c[i]) continue;
		int t=dfs(y,min(w[i],lim-flow),cost);
		w[i]-=t; w[i^1]+=t;
		flow+=t; cost+=t*c[i];
		if (flow==lim) return lim;
	}
	return flow;
}

inline ll costflow(){
	int flow=0; ll cost=0;
	while (spfa())
		do{
			memset(mark,0,sizeof(mark));
			flow+=dfs(S,inf,cost);
		}while (mark[T]);
	return cost;
}

int main(){
	int n,m,k,c,d,lim=101;
	cin>>n>>m>>k>>c>>d;
	for (int i=0;i<k;i++){
		int x; cin>>x; x--;
		addedge(S,x,1,0);
	}
	for (int i=0;i<lim;i++)
		addedge(i*n,T,k,c*i);
	for (int i=0;i<n;i++)
		for (int j=0;j<lim-1;j++)
			addedge(i+j*n,i+(j+1)*n,k,0);
	while (m--){
		int x,y; cin>>x>>y; x--,y--;
		for (int i=0;i<lim-1;i++)
			for (int j=k-1;~j;j--){
				addedge(x+i*n,y+(i+1)*n,1,d*(j<<1|1));
				addedge(y+i*n,x+(i+1)*n,1,d*(j<<1|1));
			}
	}
	cout<<costflow();
	return 0;
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#define inf 1e9
#define K 210
#define N 100010
#define M 2000100
using namespace std;
inline int read()
{
	char ch=getchar();
    int s=0,w=1;
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
	return s*w;
}
struct Edge
{
	int next,to,fl,v;
}e[M<<1];
int cnt=1,head[N];
int s,t;
int pre[N],dist[N],vis[N];
queue<int>Q;
int minn[N];
int n,m,k,c,d;
int A[K];
int v[K][K];
inline void add_edge(int from,int to,int fl,int v){e[++cnt].to=to;e[cnt].next=head[from];e[cnt].fl=fl;e[cnt].v=v;head[from]=cnt;}
void update(int x,int flow)
{
	e[pre[x]].fl-=flow;
	e[pre[x]^1].fl+=flow;
	if(e[pre[x]^1].to)update(e[pre[x]^1].to,flow);
}
inline int spfa()
{
	memset(vis,0,sizeof(vis));while(!Q.empty())Q.pop();
	for(register int i=1;i<=t;i++)dist[i]=inf;
	minn[s]=inf;dist[s]=0;Q.push(s);vis[s]=1;
	while(!Q.empty())
	{
		int x=Q.front();vis[x]=0;Q.pop();
		for(register int i=head[x];i;i=e[i].next)
		{
			if(e[i].fl&&dist[e[i].to]>dist[x]+e[i].v)
			{
				dist[e[i].to]=dist[x]+e[i].v;
				minn[e[i].to]=min(minn[x],e[i].fl);
				pre[e[i].to]=i;
				if(!vis[e[i].to])
				{
					vis[e[i].to]=1;
					Q.push(e[i].to);
				}
			}
		}
	}
	if(dist[t]==inf)return inf;
	update(t,minn[t]);
	return dist[t]*minn[t];
}
inline int EK()
{
	int sum=0;
	while(1)
	{
		int x=spfa();
		if(x==inf)return sum;
		sum+=x;
	}
	return sum;
}
inline int idx(int pos,int x){return pos*n+x;}
int main()
{
	n=read(),m=read(),k=read(),c=read(),d=read();
	t=n*201+1;
	for(register int i=1;i<=k;i++)A[i]=read();
	for(register int i=1;i<=m;i++)
	{
		int x=read(),y=read();
		v[x][y]++,v[y][x]++;
	}
	for(register int i=1;i<=k;i++)
	{
		add_edge(s,idx(0,A[i]),1,0);add_edge(idx(0,A[i]),s,0,0);
	}
	for(register int p=0;p<=199;p++)
	{
		for(register int i=1;i<=n;i++)
		{
			for(register int j=1;j<=n;j++)
			{
				if(!v[i][j])continue;
				for(register int k=1;k<=v[i][j];k++)
				{
					for(register int l=1;l<=n;l++)
					{
						add_edge(idx(p,i),idx(p+1,j),1,2*d*l-d);
						add_edge(idx(p+1,j),idx(p,i),0,d-2*d*l);
					}
				}
			}
			add_edge(idx(p,i),idx(p+1,i),inf,0);add_edge(idx(p+1,i),idx(p,i),0,0);
		}
	}
	for(register int p=0;p<=200;p++)
	{
		add_edge(idx(p,1),t,inf,c*p);add_edge(t,idx(p,1),0,-c*p);
	}
	printf("%d\n",EK());
	return 0;
}


#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
using i64=int_least64_t;

namespace std
{
    // hash
    template <class T> size_t hash_combine(size_t seed, T const &key) { return seed ^ (hash<T>()(key) + 0x9e3779b9 + (seed << 6) + (seed >> 2)); }
    template <class T, class U> struct hash<pair<T, U>> { size_t operator()(pair<T, U> const &pr) const { return hash_combine(hash_combine(0, pr.first), pr.second); } };
    template <class tuple_t, size_t index = tuple_size<tuple_t>::value - 1> struct tuple_hash_calc { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(tuple_hash_calc<tuple_t, index - 1>::apply(seed, t), get<index>(t)); } };
    template <class tuple_t> struct tuple_hash_calc<tuple_t, 0> { static size_t apply(size_t seed, tuple_t const &t) { return hash_combine(seed, get<0>(t)); } };
    template <class... T> struct hash<tuple<T...>> { size_t operator()(tuple<T...> const &t) const { return tuple_hash_calc<tuple<T...>>::apply(0, t); } };
    // iostream
    template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) { return is >> p.first >> p.second; }
    template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { return os << p.first << ' ' << p.second; }
    template <class tuple_t, size_t index> struct tupleis { static istream &apply(istream &is, tuple_t &t) { tupleis<tuple_t, index - 1>::apply(is, t); return is >> get<index>(t); } };
    template <class tuple_t> struct tupleis<tuple_t, SIZE_MAX> { static istream &apply(istream &is, tuple_t &t) { return is; } };
    template <class... T> istream &operator>>(istream &is, tuple<T...> &t) { return tupleis<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(is, t); }
    template <> istream &operator>>(istream &is, tuple<> &t) { return is; }
    template <class tuple_t, size_t index> struct tupleos { static ostream &apply(ostream &os, const tuple_t &t) { tupleos<tuple_t, index - 1>::apply(os, t); return os << ' ' << get<index>(t); } };
    template <class tuple_t> struct tupleos<tuple_t, 0> { static ostream &apply(ostream &os, const tuple_t &t) { return os << get<0>(t); } };
    template <class... T> ostream &operator<<(ostream &os, const tuple<T...> &t) { return tupleos<tuple<T...>, tuple_size<tuple<T...>>::value - 1>::apply(os, t); }
    template <> ostream &operator<<(ostream &os, const tuple<> &t) { return os; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    istream& operator>>(istream& is, Container &cont) { for(auto&& e : cont) is >> e; return is; }
    template <class Container, typename Value = typename Container::value_type, enable_if_t<!is_same<decay_t<Container>, string>::value, nullptr_t> = nullptr>
    ostream& operator<<(ostream& os, const Container &cont) { bool flag = 1; for(auto&& e : cont) flag ? flag = 0 : (os << ' ', 0), os << e; return os; }
} // namespace std

#include <cassert>
#include <list>
#include <vector>

// Base class of flow algorithms
template <class cap_t, class cost_t>
struct flow_base
{
    struct edge_t
    {
        size_t src, dst;
        cap_t cap; cost_t cost;
        edge_t *rev;
        edge_t(size_t _src, size_t _dst, cap_t _cap, cost_t _cost, edge_t *_rev)
            : src(_src), dst(_dst), cap(_cap), cost(_cost), rev(_rev) {}
    }; // struct edge_t

protected:
    using adj_type = std::vector<std::list<edge_t>>;
    adj_type adj;

public:
    flow_base(size_t _n = 0) : adj(_n) {}

    flow_base(const flow_base& other) : adj(other.size())
    {
        for(size_t node{0}; node != other.size(); ++node)
        {
            for(const auto &e : other[node])
            {
                if(e.src == node)
                {
                    adj[e.src].emplace_back(e);
                    adj[e.dst].emplace_back(*e.rev);
                    adj[e.src].back().rev = &adj[e.dst].back();
                    adj[e.dst].back().rev = &adj[e.src].back();
                    e.rev->src = -1;
                }
                else
                {
                    e.rev->rev->src = node;
                }
            }
        }
    }

    flow_base &operator=(const flow_base &other)
    {
        if(this != &other)
        {
            flow_base cop(other);
            std::swap(adj, cop.adj);
        }
        return *this;
    }

    size_t size() const { return adj.size(); }

    typename decltype(adj)::reference operator[](size_t node) { assert(node < size()); return adj[node]; }
    typename decltype(adj)::const_reference operator[](size_t node) const { assert(node < size()); return adj[node]; }

    void add_edge(size_t src, size_t dst, cap_t cap, cost_t cost)
    {
        assert(src < size()); assert(dst < size());
        if(cap <= 0) return;
        adj[src].emplace_back(src, dst, cap, cost, nullptr);
        adj[dst].emplace_back(dst, src, 0, -cost, nullptr);
        adj[src].back().rev = &adj[dst].back();
        adj[dst].back().rev = &adj[src].back();
    }
}; // struct flow_base

template <class cap_t, class cost_t>
class min_cost_flow : public flow_base<cap_t, cost_t>
{
    using base = flow_base<cap_t, cost_t>;
    using edge_t = typename base::edge_t;

    template <class type>
    constexpr bool valid(const type &val) const { return val != static_cast<type>(-1); }

    template <class type>
    constexpr void make_invalid(type &val) const { val = -1; }

    cost_t min_cost, total_cost;
    std::vector<cap_t> supp;
    std::vector<cost_t> ptnl, dist;
    std::vector<edge_t*> last;

    void copy_member(const min_cost_flow &other)
    {
        min_cost = other.min_cost;
        total_cost = other.total_cost;
        supp = other.supp;
        ptnl = other.ptnl;
    }

    bool Dijkstra(size_t src, const size_t dst)
    {
        const cost_t infty(total_cost + 1);
        // static std::vector<cost_t> dist(base::size(), infty);
        fill(dist.begin(), dist.end(), infty);
        dist[src] = 0;
        //*/
        std::priority_queue<std::pair<cost_t, size_t>> que;
        que.emplace(0, src);
        while(!que.empty())
        {
            auto [ndist, now] = que.top();
            ndist = -ndist, que.pop();
            if(ndist != dist[now]) continue;
            ptnl[now] += ndist;
            make_invalid(dist[now]);
            for(edge_t &e : base::adj[now])
            {
                if(!valid(dist[e.dst]) || e.cap == static_cast<cap_t>(0)) continue;
                if(dist[e.dst] + ptnl[e.dst] > ptnl[now] + e.cost)
                {
                    dist[e.dst] = ptnl[now] + e.cost - ptnl[e.dst];
                    last[e.dst] = &e;
                    que.emplace(-dist[e.dst], e.dst);
                }
            }
        }
        /*/
        while(valid(src))
        {
            ptnl[src] += dist[src];
            make_invalid(dist[src]);
            for(edge_t &e : base::adj[src])
            {
                if(!valid(dist[e.dst]) || e.cap == static_cast<cap_t>(0)) continue;
                if(dist[e.dst] + ptnl[e.dst] > ptnl[src] + e.cost)
                {
                    dist[e.dst] = ptnl[src] + e.cost - ptnl[e.dst];
                    last[e.dst] = &e;
                }
            }
            make_invalid(src);
            cost_t spath{infty};
            for(size_t node{}; node != base::size(); ++node)
            {
                if(!valid(dist[node])) continue;
                if(spath > dist[node])
                {
                    spath = dist[node];
                    src = node;
                }
            }
        }
        //*/
        return !valid(dist[dst]);
    }

public:
    min_cost_flow(size_t _n = 0) : base::flow_base(_n + 2), min_cost(0), total_cost(0), supp(_n + 2), ptnl(_n + 2), dist(_n + 2), last(_n + 2)  {}

    min_cost_flow(const min_cost_flow &other) : base::flow_base(other)
    {
        copy_member(other);
    }

    min_cost_flow &operator=(const min_cost_flow &other)
    {
        base::operator=(other);
        copy_member(other);
        return *this;
    }

    size_t size() const { return base::size() - 2; }

    void add_edge(size_t src, size_t dst, cap_t cap, cost_t cost)
    {
        assert(src != dst);
        if(cap <= static_cast<cap_t>(0)) return;
        if(cost < static_cast<cost_t>(0))
        {
            supp[src] -= cap;
            supp[dst] += cap;
            min_cost += cap * cost;
            total_cost -= cap * cost;
            base::add_edge(dst, src, cap, -cost);
        }
        else
        {
            total_cost += cap * cost;
            base::add_edge(src, dst, cap, cost);
        }
    }

    void supply(size_t node, cap_t vol) { supp[node] += vol; }

    bool solve()
    {
        assert(base::size() > 1);
        const size_t src(base::size() - 2), dst(src + 1);
        cap_t flow(0), supp_sum(0);
        for(size_t node{}; node != base::size(); ++node)
        {
            supp_sum += supp[node];
            if(supp[node] > static_cast<cap_t>(0))
            {
                flow += supp[node];
                add_edge(src, node, supp[node], 0);
            }
            else if(supp[node] < static_cast<cap_t>(0))
            {
                add_edge(node, dst, -supp[node], 0);
            }
            supp[node] = 0;
        }
        if(supp_sum != static_cast<cap_t>(0)) return false;
        while(flow > static_cast<cap_t>(0))
        {
            if(!Dijkstra(src, dst)) return false;
            cap_t resid{flow};
            for(size_t node{dst}; node != src; node = last[node]->src) resid = std::min(resid, last[node]->cap);
            flow -= resid;
            min_cost += ptnl[dst] * resid;
            for(size_t node{dst}; node != src; node = last[node]->src)
            {
                last[node]->cap -= resid;
                last[node]->rev->cap += resid;
            }
            // cerr << "resid: " << resid << " shortest: " << ptnl[dst] << endl;
        }
        return true;
    }

    cost_t optimal() { return solve(), min_cost; }
};

main()
{
    min_cost_flow<int,i64> mcf(6100);
    int n,m,k,c,d; cin>>n>>m>>k>>c>>d;
    const int tlim=105;
    for(int i=0; i<k; ++i)
    {
        int j; cin>>j; j--;
        mcf.supply(j,1);
    }
    for(int i=0; i<m; ++i)
    {
        int u,v; cin>>u>>v; --u,--v;
        for(int t=0; t<tlim; ++t)
        {
            int nu=u+n;
            int nv=v+n;
            for(int x=0; x<k; ++x)
            {
                mcf.add_edge(u,nv,1,c+d*(x*2+1));
                mcf.add_edge(v,nu,1,c+d*(x*2+1));
            }
            u=nu;
            v=nv;
        }
    }
    for(int i=1; i<n; ++i)
    {
        for(int t=0; t<tlim; t++)
        {
            mcf.add_edge(n*t+i,n*(t+1)+i,k,c);
        }
    }
    const int dst=mcf.size()-1;
    mcf.supply(dst,-k);
    for(int t=0; t<=tlim; ++t) mcf.add_edge(t*n,dst,k,0);
    cout << mcf.optimal() << "\n";
}


#include <bits/stdc++.h>
using namespace std;
#define _USE_MATH_DEFINES

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

// DON'T USE THESE MACROS DURING ICPC PRACTICE
#define For(i,n) for (int i=0; i<n; i++)
#define FOR(i,a,b) for (int i=a; i<=b; i++)
#define Down(i,n) for (int i=n-1; i>=0; i--)
#define DOWN(i,a,b) for (int i=b; i>=a; i--)

typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
typedef complex<ld> pt;
typedef vector<pt> pol;
typedef vector<int> vi;

const char nl = '\n';
const ll INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const ll MOD = 1e9+7;
const ld EPS = 1e-10;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());

const int T = 99;
const int C = 12;
namespace Flow {
	const int N = 50*T + 2;

  // data structures and helper functions common to all flow routines
  struct Edge { int v, r; ll f, c, p; };
  vector<Edge> adj[N]; int sz[N]; ll mc;
  void init(int n=N) { mc=0; fill(sz,sz+n,0); fill(adj,adj+n,vector<Edge>()); }
  void add_edge(int a, int b, ll c=1, ll p=0) { mc = max(mc,c);
    adj[a].push_back({b, sz[b]++, 0, c, p});
    adj[b].push_back({a, sz[a]++, 0, 0, -p}); }  // change 0 to c for undirected

  // Minimum cost maximum flow, assuming there are no negative cost cycles
  // USAGE: 1) add edges 2) min_cost_flow(S, T, price, V, sparse?);
  // use O(V^2) Dijkstra for dense graphs, and O(E*log(V)) otherwise
  bool vis[N]; int par[N]; ll pot[N], dist[N];
  void pot_init(int n) { fill(pot, pot+n, 0);
    // if all edge costs >= 0, we don't need to run the Bellman-Ford here
    for(int i=1; i<n; i++) for(int u=0; u<n; u++) for(const Edge& e:adj[u])
      if(e.c) pot[e.v] = min(pot[e.v], pot[u] + e.p); }
  ll mcf(int s, int t, ll& price, int n, bool sparse) {
    fill(vis, vis+n, 0); fill(dist, dist+n, INF); dist[s] = 0;
    // only need one of the branches below
    if(sparse) { // replace priority_queue with queue for SPFA
      priority_queue<pair<ll,int>> dk; dk.push({0,s}); while(!dk.empty()) {
        int u = dk.top().second; dk.pop(); if(vis[u]) continue;
        for(const Edge& e:adj[u]) {
          if (e.f < e.c && dist[e.v] > dist[u] + pot[u] - pot[e.v] + e.p) {
            dist[e.v] = dist[u] + pot[u] - pot[e.v] + e.p; par[e.v] = e.r;
            dk.push({-dist[e.v], e.v}); } } }
    } else { // dense
      for(int u = s; u != -1; ) { vis[u] = true; for(const Edge& e: adj[u]) {
        if (e.f < e.c && dist[e.v] > dist[u] + pot[u] - pot[e.v] + e.p) {
          dist[e.v] = dist[u] + pot[u] - pot[e.v] + e.p; par[e.v] = e.r; } }
      u = -1; ll best = INF;
      for(int i=0; i<n; i++) if(!vis[i] && dist[i]<best) best = dist[u=i]; }
    } // end branches
    if (dist[t] >= INF) { return 0; } ll df = INF;
    for(int u = t; u != s; ) { const Edge& r = adj[u][par[u]];
      df = min(df, adj[r.v][r.r].c - adj[r.v][r.r].f); u = r.v; }
    for(int u = t; u != s; ) { Edge& r=adj[u][par[u]], &e=adj[r.v][r.r];
      e.f += df; r.f -= df; price += df*e.p; u = r.v; }
    for(int i=0; i<n; i++) { pot[i] = min(INF, dist[i]+pot[i]); } return df; }
  ll min_cost_flow(int s, int t, ll& price, int n=N, bool sparse=false) {
    //pot_init(n);
		ll flow = price = 0;
		while(ll df=mcf(s, t, price, n, sparse)) { flow += df; } return flow; }
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cout << fixed << setprecision(10);

	int n,m,k,c,d;
	cin>>n>>m>>k>>c>>d;

	const int source = 0;
	const int sink = n*T+1;

	for(int i=0;i<k;i++) {
		int a;
		cin>>a;
		Flow::add_edge(source, a, 1, 0);
	}
	for(int t=0;t<T;t++) {
		Flow::add_edge(1+t*n, sink, INF, 0);
		if(t>0) {
			for(int i=1;i<=n;i++) {
				Flow::add_edge(i+(t-1)*n, i+t*n, INF, c);
			}
		}
	}

	for(int i=0;i<m;i++) {
		int a, b;
		cin >> a >> b;
		for(int j=0;j<C;j++) {
			int cost = (j+1)*(j+1) - j*j;
			for(int t=1;t<T;t++) {
				Flow::add_edge(a+(t-1)*n, b+t*n, 1, cost*d + c);
				Flow::add_edge(b+(t-1)*n, a+t*n, 1, cost*d + c);
			}
		}
	}

	ll price, flow = Flow::min_cost_flow(source, sink, price, sink+1, true);
	assert(flow==k);
	cout << price << nl;

	return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int inf = INT_MAX;

namespace mcmf {

const int N = 10001;
struct edge { int v, p; int c, w; };
vector<edge> g[N];
int vis[N], cur[N], n;
int dis[N], pot[N];

int addv(int c) {
    while (c--) g[n++].clear();
    return n - 1;
}

void adde(int u, int v, int c, int w) {
    g[u].push_back({ v, (int)g[v].size(), c, w });
    g[v].push_back({ u, (int)g[u].size() - 1, 0, -w });
}

bool dijkstra(int s, int t) {
    fill_n(dis, n, inf);
    fill_n(vis, n, 0);
    typedef pair<int, int> pli;
    priority_queue<pli, vector<pli>, greater<pli>> q;
    q.push({ dis[s] = 0, s });
    while (!q.empty()) {
        int u; int du; tie(du, u) = q.top(); q.pop();
        if (vis[u]) continue; vis[u] = 1;
        for (edge e : g[u]) {
            int v = e.v; int dv = du + pot[u] + e.w - pot[v];
            if (!e.c || vis[v] || dis[v] <= dv) continue;
            q.push({ dis[v] = dv, v });
        }
    }
    return vis[t];
}

bool dinic_bfs(int s, int t) {
    fill_n(vis, n, 0);
    queue<int> q; q.push(s); vis[s] = 1;
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (edge e : g[u]) {
            int v = e.v;
            if (vis[v] || !e.c) continue;
            if (dis[v] != dis[u] + e.w - pot[v] + pot[u]) continue;
            vis[v] = vis[u] + 1; q.push(v);
        }
    }
    return vis[t] != 0;
}

int dinic_dfs(int u, int t, int f) {
    if (u == t)
        return f;
    int sf = 0;
    for (int& i = cur[u]; i != g[u].size(); ++i) {
        edge& e = g[u][i]; int v = e.v;
        if (!e.c || vis[v] != vis[u] + 1) continue;
        if (dis[v] != dis[u] + e.w - pot[v] + pot[u]) continue;
        int df = dinic_dfs(v, t, min(e.c, f));
        //if (df && u != 12 && v != 12 && u != 13 && v != 13) cout << u << ' ' << v << ' ' << df << ' ' << df * e.w << endl;
        sf += df; f -= df; e.c -= df; g[v][e.p].c += df;
        if (!f) break;
    }
    return sf;
}

pair<int, int> mincostflow(int s, int t, int mf) {
    int sf = 0, sc = 0;
    fill_n(pot, n, 0);
    while (dijkstra(s, t)) {
        int f = 0;
        while (dinic_bfs(s, t)) {
            fill_n(cur, n, 0);
            int df = dinic_dfs(s, t, mf);
            mf -= df; f += df;
            if (!mf) break;
        }
        sf += f; sc += (dis[t] + pot[t]) * f;
        for (int i = 0; i < n; ++i) pot[i] += dis[i];
        if (!mf) break;
    }
    return { sf, sc };
}

}

int main(void){
    int n, m, k, c, d;
    scanf("%d %d %d %d %d", &n, &m, &k, &c, &d);
    int l = max(n, k) * 2;
    mcmf::addv(l * n);
    int s = mcmf::addv(1), t = mcmf::addv(1);
    for (int j = 0; j < k; ++j) {
        int a; scanf("%d", &a);
        a--;
        mcmf::adde(s, a, 1, 0);
    }
    for (int z = 1; z <= m; ++z) {
        int u, v; scanf("%d %d", &u, &v);
        u--; v--;
        for (int i = 0; i + 1 < l; ++i) {
            int u1 = u + i * n, v1 = v + (i + 1) * n;
            int u2 = u + (i + 1) * n, v2 = v + i * n;
            for (int j = 0; j < k; ++j) {
                mcmf::adde(u1, v1, 1, c + d * (2 * j + 1));
                mcmf::adde(v2, u2, 1, c + d * (2 * j + 1));
            }
        }
    }
    for (int i = 0; i + 1 < l; ++i) {
        for (int j = 0; j < n; ++j) {
            int u = j + i * n, v = j + (i + 1) * n;
            mcmf::adde(u, v, inf, c);
        }
    }
    for (int i = 0; i < l; ++i)
        mcmf::adde(i * n, t, inf, 0);
    printf("%d\n", mcmf::mincostflow(s, t, inf).second);

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define _USE_MATH_DEFINES

#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
template <typename T>
using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

// DON'T USE THESE MACROS DURING ICPC PRACTICE
#define For(i,n) for (int i=0; i<n; i++)
#define FOR(i,a,b) for (int i=a; i<=b; i++)
#define Down(i,n) for (int i=n-1; i>=0; i--)
#define DOWN(i,a,b) for (int i=b; i>=a; i--)

typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
typedef complex<ld> pt;
typedef vector<pt> pol;
typedef vector<int> vi;

const char nl = '\n';
const ll INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const ll MOD = 1e9+7;
const ld EPS = 1e-10;
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());

const int T = 99;
const int C = 12;
namespace Flow {
	const int N = 50*T + 2;

  // data structures and helper functions common to all flow routines
  struct Edge { int v, r; ll f, c, p; };
  vector<Edge> adj[N]; int sz[N]; ll mc;
  void init(int n=N) { mc=0; fill(sz,sz+n,0); fill(adj,adj+n,vector<Edge>()); }
  void add_edge(int a, int b, ll c=1, ll p=0) { mc = max(mc,c);
    adj[a].push_back({b, sz[b]++, 0, c, p});
    adj[b].push_back({a, sz[a]++, 0, 0, -p}); }  // change 0 to c for undirected

  // Minimum cost maximum flow, assuming there are no negative cost cycles
  // USAGE: 1) add edges 2) min_cost_flow(S, T, price, V, sparse?);
  // use O(V^2) Dijkstra for dense graphs, and O(E*log(V)) otherwise
  bool vis[N]; int par[N]; ll pot[N], dist[N];
  void pot_init(int n) { fill(pot, pot+n, 0);
    // if all edge costs >= 0, we don't need to run the Bellman-Ford here
    for(int i=1; i<n; i++) for(int u=0; u<n; u++) for(const Edge& e:adj[u])
      if(e.c) pot[e.v] = min(pot[e.v], pot[u] + e.p); }
  ll mcf(int s, int t, ll& price, int n, bool sparse, ll lb=1) {
    fill(vis, vis+n, 0); fill(dist, dist+n, INF); dist[s] = 0;
    // only need one of the branches below
    if(sparse) { // replace priority_queue with queue for SPFA
      priority_queue<pair<ll,int>> dk; dk.push({0,s}); while(!dk.empty()) {
        int u = dk.top().second; dk.pop(); if(vis[u]) continue;
        for(const Edge& e:adj[u]) {
          if (e.f <= e.c-lb && dist[e.v] > dist[u] + pot[u] - pot[e.v] + e.p) {
            dist[e.v] = dist[u] + pot[u] - pot[e.v] + e.p; par[e.v] = e.r;
            dk.push({-dist[e.v], e.v}); } } }
    } else { // dense
      for(int u = s; u != -1; ) { vis[u] = true; for(const Edge& e: adj[u]) {
        if (e.f <= e.c-lb && dist[e.v] > dist[u] + pot[u] - pot[e.v] + e.p) {
          dist[e.v] = dist[u] + pot[u] - pot[e.v] + e.p; par[e.v] = e.r; } }
      u = -1; ll best = INF;
      for(int i=0; i<n; i++) if(!vis[i] && dist[i]<best) best = dist[u=i]; }
    } // end branches
    if (dist[t] >= INF) { return 0; } ll df = INF;
    for(int u = t; u != s; ) { const Edge& r = adj[u][par[u]];
      df = min(df, adj[r.v][r.r].c - adj[r.v][r.r].f); u = r.v; }
    for(int u = t; u != s; ) { Edge& r=adj[u][par[u]], &e=adj[r.v][r.r];
      e.f += df; r.f -= df; price += df*e.p; u = r.v; }
    for(int i=0; i<n; i++) { pot[i] = min(INF, dist[i]+pot[i]); } return df; }
  ll min_cost_flow(int s, int t, ll& price, int n=N, bool sparse=false) {
    pot_init(n); ll flow = price = 0;
		for(ll lb=1<<30;lb>0;lb/=2) {
			while(ll df=mcf(s, t, price, n, sparse, lb)) { flow += df; }
		} return flow; }
}

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cout << fixed << setprecision(10);

	int n,m,k,c,d;
	cin>>n>>m>>k>>c>>d;

	const int source = 0;
	const int sink = n*T+1;

	for(int i=0;i<k;i++) {
		int a;
		cin>>a;
		Flow::add_edge(source, a, 1, 0);
	}
	for(int t=0;t<T;t++) {
		Flow::add_edge(1+t*n, sink, INF, 0);
		if(t>0) {
			for(int i=1;i<=n;i++) {
				Flow::add_edge(i+(t-1)*n, i+t*n, INF, c);
			}
		}
	}

	for(int i=0;i<m;i++) {
		int a, b;
		cin >> a >> b;
		for(int j=0;j<C;j++) {
			int cost = (j+1)*(j+1) - j*j;
			for(int t=1;t<T;t++) {
				Flow::add_edge(a+(t-1)*n, b+t*n, 1, cost*d + c);
				Flow::add_edge(b+(t-1)*n, a+t*n, 1, cost*d + c);
			}
		}
	}

	ll price, flow = Flow::min_cost_flow(source, sink, price, sink+1, true);
	assert(flow==k);
	cout << price << nl;

	return 0;
}


#include<bits/stdc++.h>
#define maxn 5000010
#define inf 1000000000
#define p(x,k) (x+(k-1)*n)
using namespace std;
template<typename T> inline void read(T &x)
{
    x=0;char c=getchar();bool flag=false;
    while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    if(flag)x=-x;
}
int n,m,k,v1,v2,s,t;
int dis[maxn];
bool vis[maxn];
struct edge
{
    int to,nxt,v,c;
}e[maxn];
int head[maxn],edge_cnt=1;
void add(int from,int to,int val,int cost)
{
	e[++edge_cnt]=(edge){to,head[from],val,cost},head[from]=edge_cnt;
    e[++edge_cnt]=(edge){from,head[to],0,-cost},head[to]=edge_cnt;
}
bool spfa()
{
    queue<int> q;
    for(int i=s;i<=t;++i) dis[i]=inf,vis[i]=false;
    q.push(s),dis[s]=0,vis[s]=true;
    while(!q.empty())
    {
        int x=q.front();
        q.pop(),vis[x]=false;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to,c=e[i].c;
            if(dis[y]<=dis[x]+c||!e[i].v) continue;
            dis[y]=dis[x]+c;
            if(!vis[y]) vis[y]=true,q.push(y);
        }
    }
    return dis[t]!=inf;
}
int dfs(int x,int lim)
{
    if(x==t) return lim;
    vis[x]=true;
    int flow,res=lim;
    for(int i=head[x];i;i=e[i].nxt)
    {
        int y=e[i].to,v=e[i].v;
        if(dis[y]!=dis[x]+e[i].c||!v||vis[y]) continue;
        if(flow=dfs(y,min(res,v)))
        {
            res-=flow;
            e[i].v-=flow;
            e[i^1].v+=flow;
            if(!res) break;
        }
    }
    return lim-res;
}
int dinic()
{
    int flow,sum=0;
    while(spfa())
        while(flow=dfs(s,inf))
            sum+=flow*dis[t];
    return sum;
}
int main()
{
    read(n),read(m),read(k),read(v1),read(v2),t=p(n,110)+1;
    for(int i=2;i<=110;++i) add(p(1,i),t,inf,0);
    for(int i=2;i<=n;++i)
        for(int j=1;j<110;++j)
            add(p(i,j),p(i,j+1),inf,v1);
    for(int i=1,x;i<=k;++i) read(x),add(s,p(x,1),1,0);
    for(int i=1;i<=m;++i)
    {
        int x,y;
        read(x),read(y);
        for(int j=1;j<110;++j)
            for(int l=1;l<=k;++l)
                add(p(x,j),p(y,j+1),1,v2*(2*l-1)+v1),add(p(y,j),p(x,j+1),1,v2*(2*l-1)+v1);
    }
    printf("%d",dinic());
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int TIME=150, inf=1e9, sz=1e4;

int src, dst;

struct edge{
    int to, f, cap, rev, cost;
};
vector < edge > g[sz];

void add_edge(int a, int b, int cap, int cost){
    edge ab = {b, 0, cap, int(g[b].size()), cost};
    edge ba = {a, 0, 0, int(g[a].size()), -cost};
    g[a].push_back(ab);
    g[b].push_back(ba);
}

int d[sz];
struct Cmp{
    inline bool operator()(const int &lhs, const int &rhs){
        if(d[lhs] != d[rhs]) return d[lhs] < d[rhs];
        return lhs < rhs;
    }
};

// O(n^2*m*logm) or O(m*flow*logm)
pair < int, int > mincost(int n){

    set < int, Cmp > q;
    int pot[n], prevedge[n], prevnode[n];
    int flow = 0, flowcost = 0, INF = 1e9;

    for(int a=0; a<n; a++) pot[a]=0;
    while(true){
        for(int i = 0; i < n; i++) d[i] = INF;
        d[src] = 0;
        q.insert(src);
        while(!q.empty()){
            int v = *q.begin();
            q.erase(q.begin());
            for(int i = 0; i < (int)g[v].size(); i++){
                edge e = g[v][i];
                if(e.f < e.cap){
                    int to = e.to;
                    int w = e.cost;
                    int di = d[v] + pot[v] - pot[to] + w;
                    if(d[to] > di){
                        q.erase(to);
                        d[to] = di;
                        prevnode[to] = v;
                        prevedge[to] = i;
                        q.insert(to);
                    }
                }
            }
        }
        if(d[dst] == INF) break;
        for(int i = 0; i < n; i++) pot[i] += d[i];
        int df = INF;
        for(int v = dst; v != src; v = prevnode[v]){
            int par = prevnode[v];
            int i = prevedge[v];
            df = min(df, g[par][i].cap - g[par][i].f);
        }
        flow += df;
        for(int v = dst; v != src; v = prevnode[v]){
            int par = prevnode[v];
            int i = prevedge[v];
            g[par][i].f += df;
            flowcost += df * g[par][i].cost;
            g[v][g[par][i].rev].f -= df;
        }
    }
    return make_pair(flow, flowcost);
}

main()
{
    //freopen("input.txt", "r", stdin);
    int n, m, k, c, d;
    cin>>n>>m>>k>>c>>d;
    src=n*TIME, dst=src+1;
    for(int a=0; a<k; a++)
    {
        int v;
        cin>>v;
        v--, add_edge(src, v*TIME, 1, 0);
    }
    for(int a=0; a<n; a++) for(int b=0; b+1<TIME; b++) add_edge(a*TIME+b, a*TIME+b+1, inf, c);
    for(int a=0; a<m; a++)
    {
        int u, v;
        cin>>u>>v;
        u--, v--;
        for(int h=0; h+1<TIME; h++)
        {
            for(int q=1; q<=n; q++)
            {
                add_edge(u*TIME+h, v*TIME+h+1, 1, c+(q*q-(q-1)*(q-1))*d);
                add_edge(v*TIME+h, u*TIME+h+1, 1, c+(q*q-(q-1)*(q-1))*d);
            }
        }
    }
    for(int a=0; a<TIME; a++) add_edge(a, dst, inf, 0);

    cout<<mincost(n*TIME+2).second;
}


#include <bits/stdc++.h>

using namespace std;

#define fore(i, s, e) for(int i = s; i < e; i++)
#define pb push_back
#define ALL(a) a.begin(), a.end()
#define SZ(a) ((int)a.size())
#define mset(a, b) memset(a, b, sizeof(a))
#define fst first
#define snd second

typedef long long ll;

typedef ll tf;
typedef ll tc;
const tf INF=1e9;
struct MCF{
	int n;
	vector<tc> prio, pot; vector<tf> curflow; vector<int> prevedge,prevnode;
	priority_queue<pair<tc, int>, vector<pair<tc, int>>, greater<pair<tc, int>>> q;
	struct edge{int to, rev; tf f, cap; tc cost;};
	vector<vector<edge>> g;
	MCF(int n):n(n),prio(n),curflow(n),prevedge(n),prevnode(n),pot(n),g(n){}
	void add_edge(int s, int t, tf cap, tc cost) {
    // cout << s << " " << t << " " << cap << endl;
		g[s].pb((edge){t,SZ(g[t]),0,cap,cost});
		g[t].pb((edge){s,SZ(g[s])-1,0,0,-cost});
	}
	pair<tf,tc> get_flow(int s, int t) {
		tf flow=0; tc flowcost=0;
    // cout << s << " " << t << endl;
		while(1){
			q.push({0, s});
			fill(ALL(prio),INF);
			prio[s]=0; curflow[s]=INF;
			while(!q.empty()) {
				auto cur=q.top();
				tc d=cur.fst;
        int u=cur.snd;
				q.pop();
				if(d!=prio[u]) continue;
				for(int i=0; i<SZ(g[u]); ++i) {
					edge &e=g[u][i];
					int v=e.to;
					if(e.cap<=e.f) continue;
					tc nprio=prio[u]+e.cost+pot[u]-pot[v];
					if(prio[v]>nprio) {
						prio[v]=nprio;
						q.push({nprio, v});
						prevnode[v]=u; prevedge[v]=i;
						curflow[v]=min(curflow[u], e.cap-e.f);
					}
				}
			}
			if(prio[t]==INF) break;
			fore(i,0,n) pot[i]+=prio[i];
			tf df=min(curflow[t], INF-flow);
			flow+=df;
			for(int v=t; v!=s; v=prevnode[v]) {
				edge &e=g[prevnode[v]][prevedge[v]];
				e.f+=df; g[v][e.rev].f-=df;
				flowcost+=df*e.cost;
			}
		}
		return {flow,flowcost};
	}
};

int T = 500; // I'm supposing this works

int main() {
  int n, m, k, c, d; cin >> n >> m >> k >> c >> d;
  int N = n*T;
  MCF mcf(N + 2);
  fore(i, 0, n) fore(j, 0, T - 1) {
    mcf.add_edge(i * T + j, i * T + j + 1, INF, c); // Wait a minute on this city
  }
  fore(i, 0, T) mcf.add_edge(i, N + 1, INF, 0); // Arrive to city 0 on time i
  fore(i, 0, k) {
    int x; cin >> x; x--;
    mcf.add_edge(N, x * T, 1, 0); // One person in city x at time 0
  }
  fore(i, 0, m) {
    int x, y; cin >> x >> y; x--, y--;
    fore(j, 0, T - 1) { // for each time
      int cur = 1;
      fore(_, 0, k) { // k different people can go there
        mcf.add_edge(x * T + j, y * T + j + 1, 1, cur * d + c);
        mcf.add_edge(y * T + j, x * T + j + 1, 1, cur * d + c);
        cur += 2; // squared cost
      }
    }
  }
  auto p = mcf.get_flow(N, N + 1);
  assert(p.fst == k);
  cout << p.snd << endl;
  return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define fore(i, s, e) for(int i = s; i < e; i++)
#define pb push_back
#define ALL(a) a.begin(), a.end()
#define SZ(a) ((int)a.size())
#define mset(a, b) memset(a, b, sizeof(a))
#define fst first
#define snd second

typedef long long ll;

typedef int tf;
typedef int tc;
const tf INF=1e9;
struct MCF{
	int n;
	vector<tc> prio, pot; vector<tf> curflow; vector<int> prevedge,prevnode;
	priority_queue<pair<tc, int>, vector<pair<tc, int>>, greater<pair<tc, int>>> q;
	struct edge{int to, rev; tf f, cap; tc cost;};
	vector<vector<edge>> g;
	MCF(int n):n(n),prio(n),curflow(n),prevedge(n),prevnode(n),pot(n),g(n){}
	void add_edge(int s, int t, tf cap, tc cost) {
    // cout << s << " " << t << " " << cap << endl;
		g[s].pb((edge){t,SZ(g[t]),0,cap,cost});
		g[t].pb((edge){s,SZ(g[s])-1,0,0,-cost});
	}
	pair<tf,tc> get_flow(int s, int t) {
		tf flow=0; tc flowcost=0;
    // cout << s << " " << t << endl;
		while(1){
			q.push({0, s});
			fill(ALL(prio),INF);
			prio[s]=0; curflow[s]=INF;
			while(!q.empty()) {
				auto cur=q.top();
				tc d=cur.fst;
        int u=cur.snd;
				q.pop();
				if(d!=prio[u]) continue;
				for(int i=0; i<SZ(g[u]); ++i) {
					edge &e=g[u][i];
					int v=e.to;
					if(e.cap<=e.f) continue;
					tc nprio=prio[u]+e.cost+pot[u]-pot[v];
					if(prio[v]>nprio) {
						prio[v]=nprio;
						q.push({nprio, v});
						prevnode[v]=u; prevedge[v]=i;
						curflow[v]=min(curflow[u], e.cap-e.f);
					}
				}
			}
			if(prio[t]==INF) break;
			fore(i,0,n) pot[i]+=prio[i];
			tf df=min(curflow[t], INF-flow);
			flow+=df;
			for(int v=t; v!=s; v=prevnode[v]) {
				edge &e=g[prevnode[v]][prevedge[v]];
				e.f+=df; g[v][e.rev].f-=df;
				flowcost+=df*e.cost;
			}
		}
		return {flow,flowcost};
	}
};

int T = 150; // I'm supposing this works

int main() {
  int n, m, k, c, d; cin >> n >> m >> k >> c >> d;
  int N = n*T;
  MCF mcf(N + 2);
  fore(i, 0, n) fore(j, 0, T - 1) {
    mcf.add_edge(i * T + j, i * T + j + 1, INF, c); // Wait a minute on this city
  }
  fore(i, 0, T) mcf.add_edge(i, N + 1, INF, 0); // Arrive to city 0 on time i
  fore(i, 0, k) {
    int x; cin >> x; x--;
    mcf.add_edge(N, x * T, 1, 0); // One person in city x at time 0
  }
  fore(i, 0, m) {
    int x, y; cin >> x >> y; x--, y--;
    fore(j, 0, T - 1) { // for each time
      int cur = 1;
      fore(_, 0, k) { // k different people can go there
        mcf.add_edge(x * T + j, y * T + j + 1, 1, cur * d + c);
        mcf.add_edge(y * T + j, x * T + j + 1, 1, cur * d + c);
        cur += 2; // squared cost
      }
    }
  }
  auto p = mcf.get_flow(N, N + 1);
  assert(p.fst == k);
  cout << p.snd << endl;
  return 0;
}


#include<bits/stdc++.h>
#define pa pair<int,int>
#define CLR(a,x) memset(a,x,sizeof(a))
#define MP make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int ui;
typedef long double ld;
const int maxn=55,maxt=2*maxn,maxp=maxt*maxn,maxe=5*maxt*maxn*maxn;
const int inf=1e9;

inline char gc(){
	return getchar();
	static const int maxs=1<<16;static char buf[maxs],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,maxs,stdin),p1==p2)?EOF:*p1++;
}
inline ll rd(){
    ll x=0;char c=gc();bool neg=0;
    while(c<'0'||c>'9'){if(c=='-') neg=1;c=gc();}
    while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+c-'0',c=gc();
    return neg?(~x+1):x;
}

struct Edge{
	int b,l,c,ne;
}eg[maxe];
int ect=1,egh[maxp];
int N,M,K,C,D,cnt[maxn];
int id[maxn][maxt],S=1,E=2,pct=2;
bool flag[maxp];
int dis[maxp],ans;
queue<int> q;

inline void adeg(int a,int b,int c,int l){
	eg[++ect].b=b,eg[ect].ne=egh[a],egh[a]=ect;
	eg[ect].c=c,eg[ect].l=l;
}

inline void ade(int a,int b,int c,int l){
	adeg(a,b,c,l),adeg(b,a,-c,0);
}

inline bool spfa(){
	for(int i=1;i<=pct;i++) flag[i]=0,dis[i]=inf;
	dis[S]=0;q.push(S);
	while(!q.empty()){
		int p=q.front();q.pop();
		flag[p]=0;
		for(int i=egh[p];i;i=eg[i].ne){
			if(!eg[i].l) continue;
			int b=eg[i].b;
			if(dis[b]>dis[p]+eg[i].c){
				dis[b]=dis[p]+eg[i].c;
				if(!flag[b]) q.push(b),flag[b]=1;
			}
		}
	}
	return dis[E]<inf;
}

int dinic(int x,int y){
	if(x==S) return y;
	flag[x]=1;
	int tmp=y;
	for(int i=egh[x];i;i=eg[i].ne){
		int b=eg[i].b;if(flag[b]||!eg[i^1].l||dis[x]<dis[b]+eg[i^1].c) continue;
		int re=dinic(b,min(tmp,eg[i^1].l));
		if(re){
			tmp-=re,eg[i^1].l-=re,eg[i].l+=re;
			if(!tmp) break;
		}
	}return y-tmp;
}

int main(){
    //freopen("","r",stdin);
    N=rd(),M=rd(),K=rd(),C=rd(),D=rd();
    for(int i=1;i<=K;i++) cnt[rd()]++;
    for(int i=1;i<=N;i++){
    	for(int j=1;j<=K+M+2;j++){
    		id[i][j]=++pct;
    		if(i==1) ade(id[i][j],E,C*(j-1),inf);
    		if(j>1) ade(id[i][j-1],id[i][j],0,inf);
    	}
    	if(cnt[i]) ade(S,id[i][1],0,cnt[i]);
    }
    for(int i=1;i<=M;i++){
    	int a=rd(),b=rd();
    	for(int j=1;j<=K+M+1;j++){
    		for(int k=1;k<=2*K-1;k+=2){
    			ade(id[a][j],id[b][j+1],k*D,1);
    			ade(id[b][j],id[a][j+1],k*D,1);
    		}
    	}
    }
    int nn=0;
    while(spfa()){
    	int aa=-1;
    	while(aa){
    		CLR(flag,0);
    		aa=dinic(E,inf);
    		nn+=aa,ans+=dis[E]*aa;
    	}
    }
    assert(nn==K);
	printf("%d\n",ans);
    return 0;
}


#include <bits/stdc++.h>
using namespace std;

const int INF = 1000*1000*1000;

struct rib {
	int b, u, c, f;
	size_t back;
};

void add_rib (vector < vector<rib> > & g, int a, int b, int u, int c) {
	rib r1 = { b, u, c, 0, g[b].size() };
	rib r2 = { a, 0, -c, 0, g[a].size() };
	g[a].push_back (r1);
	g[b].push_back (r2);
}

int main()
{
	int N, m, k, c, d;
	scanf("%d %d %d %d %d", &N, &m, &k, &c, &d);
	int n = N * 101 + 2;
	vector < vector<rib> > g (n);
	for (int i = 0; i < k; i++) {
		int x;
		scanf("%d", &x);
		x--;
		add_rib(g, n - 2, x*101, 1, 0);
	}
	for (int i = 0; i < 101; i++)
	{
		add_rib(g, i, n-1, INF, i*c);
	}
	for (int i = 1; i < N; i++) {
		for (int j = 0; j+1 < 101; j++) {
			add_rib(g, i*101 + j, i*101 + j + 1, INF, 0);
		}
	}
	for (int i = 0; i < m; i++) {
		int u, v;
		scanf("%d %d", &u, &v);
		u--;
		v--;
		for (int j = 0; j+1 < 101; j++) {
			for (int K = 1; K <= k; K++) {
				add_rib(g, u*101 + j, v*101 + j + 1, 1, d*K*K - d*(K-1)*(K-1));
				add_rib(g, v*101 + j, u*101 + j + 1, 1, d*K*K - d*(K-1)*(K-1));
			}
		}
	}
	int s, t;
	s = n-2;
	t = n-1;
	int flow = 0, cost = 0;
	while (flow < k) {
		vector<int> id (n, 0);
		vector<int> d (n, INF);
		vector<int> q (n);
		vector<int> p (n);
		vector<size_t> p_rib (n);
		int qh=0, qt=0;
		q[qt++] = s;
		d[s] = 0;
		while (qh != qt) {
			int v = q[qh++];
			id[v] = 2;
			if (qh == n)  qh = 0;
			for (size_t i=0; i<g[v].size(); ++i) {
				rib & r = g[v][i];
				if (r.f < r.u && d[v] + r.c < d[r.b]) {
					d[r.b] = d[v] + r.c;
					if (id[r.b] == 0) {
						q[qt++] = r.b;
						if (qt == n)  qt = 0;
					}
					else if (id[r.b] == 2) {
						if (--qh == -1)  qh = n-1;
						q[qh] = r.b;
					}
					id[r.b] = 1;
					p[r.b] = v;
					p_rib[r.b] = i;
				}
			}
		}
		if (d[t] == INF)  break;
		int addflow = k - flow;
		for (int v=t; v!=s; v=p[v]) {
			int pv = p[v];  size_t pr = p_rib[v];
			addflow = min (addflow, g[pv][pr].u - g[pv][pr].f);
		}
		for (int v=t; v!=s; v=p[v]) {
			int pv = p[v];  size_t pr = p_rib[v],  r = g[pv][pr].back;
			g[pv][pr].f += addflow;
			g[v][r].f -= addflow;
			cost += g[pv][pr].c * addflow;
		}
		flow += addflow;
	}
	assert(flow == k);
	cout<<cost<<endl;

}


#include <bits/stdc++.h>
#define fst first
#define snd second
#define fore(i,a,b) for(int i=a,ThxDem=b;i<ThxDem;++i)
#define pb push_back
#define ALL(s) s.begin(),s.end()
#define FIN ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define SZ(s) int(s.size())
using namespace std;
typedef long long ll;
typedef pair<int,int> ii;

const int INF=1e9;
struct MCF {
	int n, m, k, t;
	vector<int> u,v,prio,curflow,prevedge,prevnode,pot;
	struct Edge {
		int to, f, cap, cost, rev;
	};
	vector<vector<Edge>> adj;
	MCF(int n):n(n),u(n),v(n),prio(n),curflow(n),prevedge(n),prevnode(n),pot(n),adj(n){}
	priority_queue<ll, vector<ll>, greater<ll> > q;
	inline void addEdge(int s, int t, int cap, int cost) {
		Edge a = {t, 0, cap, cost, SZ(adj[t])};
		Edge b = {s, 0, 0, -cost, SZ(adj[s])};
		adj[s].push_back(a);
		adj[t].push_back(b);
	}
	inline pair<int, int> minCostFlow(int s, int t) {
		int flow=0, flowCost=0;
		while(flow<INF) {
			q.push(s);
			fill(ALL(prio), INT_MAX);
			prio[s]=0;
			curflow[s]=INT_MAX;
			while(!q.empty()) {
				ll cur=q.top();
				int d=cur>>32, u=cur;
				q.pop();
				if(d!=prio[u])
					continue;
				for(int i=0; i<SZ(adj[u]); ++i) {
					Edge &e=adj[u][i];
					int v=e.to;
					if (e.cap<=e.f)
						continue;
					int nprio=prio[u]+e.cost+pot[u]-pot[v];
					if (prio[v]>nprio) {
						prio[v]=nprio;
						q.push(((ll)nprio<<32)+v);
						prevnode[v]=u;
						prevedge[v]=i;
						curflow[v]=min(curflow[u], e.cap-e.f);
					}
				}
			}
			if(prio[t]==INT_MAX)
				break;
			for(int i=0; i<n; ++i)
				pot[i]+=prio[i];
			int df=min(curflow[t], INF-flow);
			flow+=df;
			for(int v=t; v!=s; v=prevnode[v]) {
				Edge &e=adj[prevnode[v]][prevedge[v]];
				e.f+=df;
				adj[v][e.rev].f-=df;
				flowCost+=df*e.cost;
			}
		}
		return make_pair(flow, flowCost);
	}
};

int n,m,k,c,d;

int main(){
	scanf("%d%d%d%d%d",&n,&m,&k,&c,&d);
	MCF nt(6+107*n);
	fore(_,0,k){
		int x;
		scanf("%d",&x);x--;
		nt.addEdge(0,1+x,1,0);
	}
	fore(_,0,m){
		int x,y;
		scanf("%d%d",&x,&y);x--;y--;
		fore(i,0,105){
			fore(j,0,51){
				nt.addEdge(1+i*n+x,1+(i+1)*n+y,1,c+d*(2*j+1));
				nt.addEdge(1+i*n+y,1+(i+1)*n+x,1,c+d*(2*j+1));
			}
		}
	}
	fore(i,0,105)fore(j,0,n)nt.addEdge(1+i*n+j,1+(i+1)*n+j,51,c);
	fore(i,0,105)nt.addEdge(1+i*n,1+105*n,51,0);
	auto ans=nt.minCostFlow(0,1+105*n);
	printf("%d\n",ans.snd);
	return 0;
}


#include <iostream>
#include <string>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <ctime>
#include <set>
#include <map>
#include <unordered_map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <assert.h>
#include <iomanip>
#include <bitset>
using namespace std;
#define vi vector<int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define all(x) x.begin(),x.end()
#define SZ(x) (int)(x.size())
#define rep(i,a,b) for(int i=a;i<b;i++)
#define per(i,a,b) for(int i=b-1;i>=a;i--)
#define inf 1000000007
#define mod 1000000007
#define x first
#define y second
#define pi acos(-1.0)
#define DBG(x) cerr<<(#x)<<"="<<x<<"\n";

#define FOREACH(it,x) for(__typeof(x.begin()) it=x.begin();it!=x.end();it++)
#define ull unsigned long long
#define ll long long
#define N 500005

template <class T,class U>inline void Max(T &a,U b){if(a<b)a=b;}
template <class T,class U>inline void Min(T &a,U b){if(a>b)a=b;}

//FILE* outFile;

inline void add(int &a,int b){a+=b;while(a>=mod)a-=mod;}
inline int gcd(int a, int b){if(b == 0)return a; return gcd(b, a%b);}
int pow(int a,int b){
    int ans=1;
    while(b){
        if(b&1)ans=ans*(ll)a%mod;
        a=(ll)a*a%mod;b>>=1;
    }
    return ans;
}

const int M = 105;
int a[51], id[51][M];
pii b[51];
int cnt, head[N], d[N], p[N], vis[N];
struct node{
    int v, c, w, next;
}g[N<<2];
void add(int a, int b, int c, int w){
    g[cnt] = {b, c, w, head[a]}, head[a] = cnt++;
    g[cnt] = {a, 0, -w, head[b]}, head[b] = cnt++;
}
int bfs(int s, int t){
    rep(i, 0, t+1)d[i] = inf, vis[i] = 0;
    queue<int>q;
    q.push(s); d[s] = 0;
    while(!q.empty()){
        int u = q.front(); q.pop(); vis[u] = 0;
        for(int i = head[u]; ~i; i = g[i].next){
            int j = g[i].v;
            if(g[i].c && d[j] > d[u] + g[i].w){
                d[j] = d[u] + g[i].w;
                p[j] = i;
                if(!vis[j]){
                    vis[j] = 1;
                    q.push(j);
                }
            }
        }
    }
    return d[t] < inf;
}
int max_flow(int s, int t){
    int ans = 0, res = 0;
    while(bfs(s, t)){
        int x = t, f = inf;
        while(x != s){
            Min(f, g[p[x]].c), x = g[p[x] ^ 1].v;
        }
        ans += f * d[t];
        res += f;
        x = t;
        while(x != s){
            g[p[x]].c -= f, g[p[x] ^ 1].c += f;
            x = g[p[x] ^ 1].v;
        }
    }
    DBG(res)
    return ans;
}
int main(){
    int j,k,i,T,ca=0, K = 0, m, n;
    int C,D;
    scanf("%d%d%d%d%d", &n, &m, &K, &C, &D);
    rep(i, 0, K)scanf("%d", &a[i]), a[i]--;
    rep(i, 0, m){
        scanf("%d%d", &b[i].x, &b[i].y);
        b[i].x--, b[i].y--;
    }
    int sz = 0;
    cnt = 0;
    memset(head, -1, sizeof(head));
    rep(i, 0, n)rep(j, 0, M)id[i][j] = sz++;
    int s = sz, t = s + 1;
    rep(i, 0, K){
        add(s, id[a[i]][0], 1, 0);
    }
    rep(i, 0, M)add(id[0][i], t, K, C * i);
    rep(i, 0, n){
        rep(j, 0, M-1){
            add(id[i][j], id[i][j+1], K, 0);
        }
    }
    rep(i, 0, m){
        int x = b[i].x, y = b[i].y;
        rep(j, 0, M-1){
            rep(k, 0, K){
                add(id[x][j], id[y][j+1], 1, D*(2*k + 1));
                add(id[y][j], id[x][j+1], 1, D*(2*k + 1));
            }
        }
    }
    int ans = max_flow(s, t);
    printf("%d\n", ans);
}


#include<bits/stdc++.h>
using namespace std;
const int N=2000005;
int tot,ne[N],fi[N],zz[N],sl[N],dis[N],S,T,n,m,x[N],y[N],flag[N],w[N],cur[N],k,c,d;
queue<int >Q;
void jb(int x,int y,int z,int v){
	ne[++tot]=fi[x];
	fi[x]=tot;
	zz[tot]=y;
	sl[tot]=z;
	w[tot]=v;
	ne[++tot]=fi[y];
	fi[y]=tot;
	zz[tot]=x;
	sl[tot]=0;
	w[tot]=-v;
}
int bfs(){
	Q.push(S);
	memset(dis,0x3f3f3f3f,sizeof dis);
	dis[S]=0;
	while (!Q.empty()){
		int now=Q.front();Q.pop();flag[now]=0;
		for (int i=fi[now];i;i=ne[i])
			if (sl[i]&&dis[zz[i]]>dis[now]+w[i]){
				dis[zz[i]]=dis[now]+w[i];
				if (!flag[zz[i]]){
					flag[zz[i]]=1;
					Q.push(zz[i]);
				}
			}
	}
	return dis[T]<=1e9;
}
int dfs(int x,int y){
	int s=0,b;
	flag[x]=1;
	if (x==T)return y;
	for (int &i=cur[x];i;i=ne[i])
		if (!flag[zz[i]]&&sl[i]&&dis[zz[i]]==dis[x]+w[i]&&(b=min(y,dfs(zz[i],min(y,sl[i]))))){
			sl[i]-=b;
			sl[i^1]+=b;
			s+=b;y-=b;
			if (!y)return s;
		}
	return s;
}
int gao(){
	int ans=0;
	while (bfs()){
		for (int i=S;i<=n+1+n*(n+k);i++)cur[i]=fi[i];
		ans+=dfs(S,1e9)*dis[T];
		memset(flag,0,sizeof flag);
	}
	return ans;
}
int main(){
	scanf("%d%d%d%d%d",&n,&m,&k,&c,&d);
	S=0,T=1;
	tot=1;
	for (int i=1;i<=k;i++){
		int x;
		scanf("%d",&x);
		jb(S,x+1,1,0);
	}
	for (int i=1;i<=m;i++)scanf("%d%d",&x[i],&y[i]);
	for (int i=0;i<=n+k;i++){
		jb(2+i*n,T,k,0);
		if (i==n+k)break;
		for (int j=1;j<=m;j++)
			for (int l=k;l>=0;l--)jb(x[j]+1+i*n,y[j]+1+i*n+n,1,(l*2+1)*d+c),jb(y[j]+1+i*n,n+x[j]+1+i*n,1,(l*2+1)*d+c);
		for (int j=1;j<=n;j++)jb(j+1+i*n,j+1+i*n+n,k,c);
	}
	printf("%d\n",gao());
}


#include<bits/stdc++.h>

using namespace std;

struct edge
{
	int y, c, f, cost;
	edge() {};
	edge(int y, int c, int f, int cost) : y(y), c(c), f(f), cost(cost) {};
};

vector<edge> e;

const int N = 14043;
vector<int> g[N];

long long ans = 0;
long long d[N];
int p[N];
int pe[N];
int inq[N];

const long long INF64 = (long long)(1e18);

int s = N - 2;
int t = N - 1;

int rem(int x)
{
	return e[x].c - e[x].f;
}

void push_flow()
{
	for(int i = 0; i < N; i++) d[i] = INF64, p[i] = -1, pe[i] = -1, inq[i] = 0;
	d[s] = 0;
	queue<int> q;
	q.push(s);
	inq[s] = 1;
	while(!q.empty())
	{
		int k = q.front();
		q.pop();
		inq[k] = 0;
		for(auto x : g[k])
		{
			if(!rem(x)) continue;
			int c = e[x].cost;
			int y = e[x].y;
			if(d[y] > d[k] + c)
			{
				d[y] = d[k] + c;
				p[y] = k;
				pe[y] = x;
				if(inq[y] == 0)
				{
					inq[y] = 1;
					q.push(y);
				}
			}
		}
	}
	int cur = t;
	while(cur != s)
	{
		e[pe[cur]].f++;
		e[pe[cur] ^ 1].f--;
		cur = p[cur];
	}
	ans += d[t];
}

void add_edge(int x, int y, int c, int cost)
{
	g[x].push_back(e.size());
	e.push_back(edge(y, c, 0, cost));
	g[y].push_back(e.size());
	e.push_back(edge(x, 0, 0, -cost));
}

int main()
{
	int n, m, k, c, d;
	cin >> n >> m >> k >> c >> d;
	for(int i = 0; i < k; i++)
	{
		int x;
		cin >> x;
		add_edge(s, x, 1, 0);
	}
	int tt = 101;
	for(int i = 0; i < tt; i++)
		add_edge(1 + i * n, t, k, i * c);
	for(int i = 0; i < m; i++)
	{
		int x, y;
		cin >> x >> y;
		for(int i = 0; i < tt - 1; i++)
			for(int j = 0; j < k; j++)
			{
				add_edge(x + i * n, y + i * n + n, 1, d * (j * 2 + 1));
				add_edge(y + i * n, x + i * n + n, 1, d * (j * 2 + 1));
			}

 	}
 	for(int i = 0; i < n; i++)
 		for(int j = 0; j < tt - 1; j++)
 			add_edge(i + j * n, i + j * n + n, k, 0);
 	for(int i = 0; i < k; i++)
 		push_flow();
 	cout << ans << endl;
}