#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;
}


//#pragma GCC optimize("O3")
//#pragma GCC target("arch=corei7-avx")
#include <bits/stdc++.h>
#ifndef ONLINE_JUDGE
# include <sys/time.h>
# include <sys/resource.h>
#endif

/*** TEMPLATE CODE STARTS HERE ***/

#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795028841971693993751
#endif

using namespace std;

typedef vector<string> vs;
typedef long long ll;
typedef complex<double> pnt;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define RA(x) begin(x), end(x)
#define FE(i, x) for (auto i = begin(x); i != end(x); ++i)
#define SZ(x) ((ll) (x).size())

template<class T>
void splitstr(const string &s, vector<T> &out)
{
    istringstream in(s);
    out.clear();
    copy(istream_iterator<T>(in), istream_iterator<T>(), back_inserter(out));
}

template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }

static void redirect(int argc, const char **argv)
{
#ifndef ONLINE_JUDGE
    struct rlimit rlim;
    getrlimit(RLIMIT_STACK, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_STACK, &rlim);
#ifndef __SANITIZE_ADDRESS__
    getrlimit(RLIMIT_DATA, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_DATA, &rlim);
#endif
#endif

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    if (argc > 1)
    {
        static filebuf f;
        f.open(argv[1], ios::in);
        cin.rdbuf(&f);
        if (!cin)
        {
            cerr << "Failed to open '" << argv[1] << "'" << endl;
            exit(1);
        }
    }

    if (argc > 2)
    {
        static filebuf f;
        f.open(argv[2], ios::out | ios::trunc);
        cout.rdbuf(&f);
        if (!cout)
        {
            cerr << "Failed to open '" << argv[2] << "'" << endl;
        }
    }
    cin.exceptions(ios::failbit);
}

/*** TEMPLATE CODE ENDS HERE */

template<typename EdgeType>
struct SimpleNode
{
    typedef EdgeType Edge;
    std::vector<Edge> edges;
};

struct SimpleEdge
{
    int trg;

    SimpleEdge() {}
    explicit SimpleEdge(int trg) : trg(trg) {}
};

template<typename T = int>
struct WeightedEdge
{
    typedef T weight_type;

    int trg;
    T weight;
    WeightedEdge() {}
    WeightedEdge(int trg, T weight) : trg(trg), weight(weight) {}
};

template<typename EdgeType, typename NodeType = SimpleNode<EdgeType> >
class GraphBase
{
public:
    typedef EdgeType Edge;
    typedef NodeType Node;

    std::vector<Node> nodes;

    int size() const { return nodes.size(); }

    int size(int id) const
    {
        assert(0 <= id && id < size());
        return nodes[id].edges.size();
    }

    NodeType &operator[](int id)
    {
        assert(0 <= id && id < size());
        return nodes[id];
    }

    const NodeType &operator[](int id) const
    {
        assert(0 <= id && id < size());
        return nodes[id];
    }

    explicit GraphBase(std::size_t size = 0) : nodes(size) {}
};

// Unweighted graph with arbitrary node type
template<typename NodeType = SimpleNode<SimpleEdge> >
class UGGraph : public GraphBase<SimpleEdge, NodeType>
{
public:
    // Add unidirectional edge
    void add1(int a, int b)
    {
        assert(0 <= a && a < this->size());
        assert(0 <= b && b < this->size());
        this->nodes[a].edges.push_back(SimpleEdge(b));
    }

    // Add bidirected edge
    void add2(int a, int b)
    {
        add1(a, b);
        add1(b, a);
    }

    explicit UGGraph(std::size_t size = 0) : GraphBase<SimpleEdge, NodeType>(size) {}
};

// Unweighted graph
typedef UGGraph<> UGraph;

// Weighted graph
template<typename T = int, typename NodeType = SimpleNode<WeightedEdge<T> > >
class WGraph : public GraphBase<WeightedEdge<T>, NodeType>
{
public:
    typedef typename GraphBase<WeightedEdge<T>, NodeType>::Edge::weight_type weight_type;
    typedef typename GraphBase<WeightedEdge<T>, NodeType>::Edge Edge;
    typedef typename GraphBase<WeightedEdge<T>, NodeType>::Node Node;

    // Add unidirectional edge
    void add1(int a, int b, T weight)
    {
        assert(0 <= a && a < this->size());
        assert(0 <= b && b < this->size());
        this->nodes[a].edges.push_back(Edge(b, weight));
    }

    // Add bidirectional edge
    void add2(int a, int b, T weight)
    {
        add1(a, b, weight);
        add1(b, a, weight);
    }

    explicit WGraph(std::size_t size = 0) : GraphBase<WeightedEdge<T>, NodeType>(size) {}
};

template<typename T = long long>
struct MCMFEdge
{
    typedef T flow_type;

    int trg;
    T cost;
    T adjcost;
    T flow;
    T cap;
    int dual;

    MCMFEdge() {}
    MCMFEdge(int trg, T cost, T cap, int dual) : trg(trg), cost(cost), adjcost(cost), flow(0), cap(cap), dual(dual) {}
};

template<typename T = long long>
class MCMFGraph : public GraphBase<MCMFEdge<T> >
{
private:
    struct pqitem
    {
        int trg;
        T prio;

        pqitem() {}
        pqitem(int trg, T prio) : trg(trg), prio(prio) {}

        bool operator<(const pqitem &b) const
        {
            return prio > b.prio;
        }
    };
public:
    typedef typename MCMFEdge<T>::flow_type flow_type;
    typedef typename GraphBase<MCMFEdge<T> >::Edge Edge;
    typedef typename GraphBase<MCMFEdge<T> >::Node Node;

    void add(int a, int b, T cost, T cap, T rcap)
    {
        assert(a >= 0 && a < this->size() && b >= 0 && b < this->size());
        assert(cap >= 0 && rcap >= 0 && cost >= 0);
        if (a == b)
            return; // no use in network flow, and complicates this function
        if (cap > 0 && rcap > 0)
        {
            add(a, b, cost, cap, 0);
            add(b, a, cost, cap, 0);
        }
        else if (rcap > 0)
        {
            add(b, a, cost, rcap, 0);
        }
        else
        {
            int da = this->size(a);
            int db = this->size(b);
            this->nodes[a].edges.push_back(Edge(b, cost, cap, db));
            this->nodes[b].edges.push_back(Edge(a, -cost, 0, da));
        }
    }

    // Returns change in flow and in cost
    std::pair<T, T> augment(int source, int sink)
    {
        const int N = this->size();
        const T big = std::numeric_limits<T>::max();

        std::vector<T> upby(N);
        std::vector<T> prio(N, big);
        std::vector<int> preve(N);
        std::priority_queue<pqitem> q;

        prio[source] = 0;
        upby[source] = big;
        q.push(pqitem(source, 0));
        while (!q.empty())
        {
            int cur = q.top().trg;
            T p = q.top().prio;
            q.pop();
            if (p != prio[cur])
                continue;
            for (int i = 0; i < this->size(cur); i++)
            {
                const Edge &e = this->nodes[cur].edges[i];
                assert(e.flow == e.cap || e.adjcost >= 0);
                T p2 = p + e.adjcost;
                if (e.flow < e.cap && p2 < prio[e.trg])
                {
                    prio[e.trg] = p2;
                    preve[e.trg] = e.dual;
                    upby[e.trg] = std::min(e.cap - e.flow, upby[cur]);
                    q.push(pqitem(e.trg, p2));
                }
            }
        }

        T up = upby[sink];
        T upcost = 0;
        if (up > 0)
        {
            int cur = sink;
            while (cur != source)
            {
                Edge &ed = this->nodes[cur].edges[preve[cur]];
                Edge &e = this->nodes[ed.trg].edges[ed.dual];
                e.flow += up;
                upcost += e.cost * up;
                ed.flow -= up;
                cur = ed.trg;
            }

            for (int i = 0; i < N; i++)
            {
                for (int j = 0; j < this->size(i); j++)
                {
                    Edge &e = this->nodes[i].edges[j];
                    e.adjcost += prio[i] - prio[e.trg];
                }
            }
        }
        return std::make_pair(up, upcost);
    }

    // Returns total flow and total cost
    std::pair<T, T> make_flow(int source, int sink)
    {
        for (int i = 0; i < this->size(); i++)
            for (int j = 0; j < this->size(i); j++)
            {
                Edge &e = this->nodes[i].edges[j];
                e.flow = 0;
                e.adjcost = e.cost;
            }

        T flow = 0;
        T cost = 0;
        std::pair<T, T> up;
        while ((up = augment(source, sink)).first != 0)
        {
            flow += up.first;
            cost += up.second;
        }
        return std::make_pair(flow, cost);
    }

    explicit MCMFGraph(std::size_t size = 0) : GraphBase<MCMFEdge<T> >(size) {}
};

int main(int argc, const char **argv)
{
    redirect(argc, argv);
    int N, M, K, C, D;
    cin >> N >> M >> K >> C >> D;
    vi a(K);
    vi starts(N);
    for (int i = 0; i < K; i++)
    {
        cin >> a[i];
        a[i]--;
        starts[a[i]]++;
    }

    int maxT = K + N + 1;
    int V = (maxT + 1) * N + 2;
    int src = V - 2;
    int sink = V - 1;
    MCMFGraph<int> g(V);
    for (int i = 0; i < N; i++)
        if (starts[i])
            g.add(src, i, 0, starts[i], 0);
    for (int t = 0; t <= maxT; t++)
        g.add(t * N, sink, 0, K, 0);
    for (int i = 0; i < N; i++)
        for (int t = 0; t < maxT; t++)
            g.add(t * N + i, (t + 1) * N + i, C, K, 0);
    for (int i = 0; i < M; i++)
    {
        int u, v;
        cin >> u >> v;
        u--;
        v--;
        for (int t = 0; t < maxT; t++)
            for (int j = 0; j < K; j++)
            {
                g.add(t * N + u, (t + 1) * N + v, C + (2 * j + 1) * D, 1, 0);
                g.add(t * N + v, (t + 1) * N + u, C + (2 * j + 1) * D, 1, 0);
            }
    }

    auto fc = g.make_flow(src, sink);
    assert(fc.first == K);
    cout << fc.second << '\n';

    return 0;
}


#include <bits/stdc++.h>

#define rep(i, n) for (int i = 0; i < (n); i++)
#define repr(i, n) for (int i = (n) - 1; i >= 0; i--)

using namespace std;
using ll = long long;

struct mincostflow {
  struct edge {
    int v;
    long long c;
    long long w;
    int r;
  };

  vector<vector<edge>> G;

  mincostflow(int n) : G(n) {}

  void add(int u, int v, long long c, long long w) {
    int i = G[u].size();
    int j = G[v].size();
    G[u].push_back({v, c, w, j});
    G[v].push_back({u, 0, -w, i});
  }

  long long run(int s, int t, long long f) {
    const int N = G.size();
    long long res = 0;
    vector<long long> H(N);
    vector<long long> D(N);
    const long long INF = 1e18;
    vector<int> PE(N), PV(N);
    while (f > 0) {
      priority_queue<pair<long long, int>> q;
      fill(D.begin(), D.end(), INF);
      D[s] = 0;
      q.emplace(0, s);
      while (!q.empty()) {
        long long d = -q.top().first;
        int u = q.top().second;
        q.pop();
        if (D[u] < d) continue;
        for (int i = 0; i < G[u].size(); i++) {
          edge e = G[u][i];
          if (e.c > 0 && D[e.v] > D[u] + e.w + H[u] - H[e.v]) {
            D[e.v] = D[u] + e.w + H[u] - H[e.v];
            q.emplace(-D[e.v], e.v);
            PV[e.v] = u;
            PE[e.v] = i;
          }
        }
      }
      if (D[t] == INF) return -1;
      for (int i = 0; i < N; i++) H[i] += D[i];
      long long d = f;
      for (int i = t; i != s; i = PV[i]) {
        d = min(d, G[PV[i]][PE[i]].c);
      }
      f -= d;
      res += d * H[t];
      for (int i = t; i != s; i = PV[i]) {
        edge &e = G[PV[i]][PE[i]];
        e.c -= d;
        G[i][e.r].c += d;
      }
    }
    return res;
  }
};

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  ll N, M, K, C, D;
  cin >> N >> M >> K >> C >> D;
  vector<int> A(K);
  rep(i, K) cin >> A[i], A[i]--;
  vector<int> us(M), vs(M);
  rep(i, M) {
    cin >> us[i] >> vs[i];
    us[i]--;
    vs[i]--;
  }
  mincostflow mcf(N*101+2);
  int s = N*101;
  int t = s + 1;
  for (int i = 0; i < K; i++) {
    mcf.add(s, A[i], 1, 0);
  }
  for (int i = 0; i <= 100; i++) {
    mcf.add(N * i, t, K, C*i);
  }
  for (int i = 0; i < 100; i++) {
    for (int j = 0; j < N; j++) {
      mcf.add(i*N+j, (i+1)*N+j, K, 0);
    }
    for (int j = 0; j < M; j++) {
      for (int k = 1; k <= K; k++) {
        mcf.add(N*i + us[j], N*(i+1) + vs[j], 1, (2*k-1)*D);
        mcf.add(N*i + vs[j], N*(i+1) + us[j], 1, (2*k-1)*D);
      }
    }
  }
  cout << mcf.run(s, t, K) << '\n';
}


#include <algorithm>
// #include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#include <bitset>
using namespace std;
typedef long long LL;
typedef double db;
const int oo=2139063143;
const int N=5010000;
const int P=1000000007;
const db eps=1e-7;
#define pritnf printf
//char buf[1<<22],*p1=buf,*p2=buf,obuf[1<<22],*O=obuf;
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
template <typename T>
inline void sc (T &x)
{
    x=0; static int p; p=1; static char c; c=getchar();
    while (!isdigit(c)) { if (c=='-') p=-1; c=getchar(); }
    while ( isdigit(c)) { x=(x<<1)+(x<<3)+(c-48); c=getchar(); }
    x*=p;
}
template <typename T>
inline void print (T x)
{
    if (x< 0) putchar('-'),x=-x;
    if (x>=10) print(x/10);
    putchar(x%10+'0');
}
template <typename T>
inline void pr (T x) { print(x),putchar('\n'); }
template <typename T1,typename T2>
void chkmax (T1 &A,T2 B) { A=A>=B?A:B; }
template <typename T1,typename T2>
void chkmin (T1 &A,T2 B) { A=A<=B?A:B; }
struct EDGE { int v,w,c,nx; }lb[N<<1]; int tot=1,top[N];
void add (int u,int v,int w,int c)
{
	lb[++tot]=(EDGE){v,w, c,top[u]},top[u]=tot;
	lb[++tot]=(EDGE){u,0,-c,top[v]},top[v]=tot;
	// printf ("%d %d %d %d\n",u,v,w,c);
}
int s,t;
int dis[N],flow[N],pre[N],las[N]; bool in[N];
bool spfa ()
{
	for (int i=1; i<=t; i++)
		dis[i]=1e9,flow[i]=pre[i]=las[i]=0,in[i]=0;
	queue <int> q;
	dis[s]=0,flow[s]=1e9,q.push (s),in[s]=1;
	while (q.size ())
	{
		int u=q.front (); q.pop (); in[u]=0;
		for (int kb=top[u]; kb; kb=lb[kb].nx)
		{
			int v=lb[kb].v,w=lb[kb].w,c=lb[kb].c;
			if (w&&dis[v]> dis[u]+c)
			{
				dis[v]=dis[u]+c;
				flow[v]=min (flow[u],w);
				pre[v]=u,las[v]=kb;
				if (!in[v]) q.push (v),in[v]=1;
			}
		}
	}
	return pre[t];
}
int maflow,micost;
void mcmf ()
{
	while (spfa ())
	{
		int u=t,fl=flow[t]; maflow+=fl,micost+=fl*dis[t];
		while (u!=s)
		{
			lb[las[u]].w-=fl,lb[las[u]^1].w+=fl;
			u=pre[u];
		}
	}
}
int n,m,k,c,d;
int main ()
{
    // freopen (".in","r",stdin);
    // freopen (".out","w",stdout);
	sc(n),sc(m),sc(k),sc(c),sc(d);
	const int B=max (n,k);
	s=n*(B*2+1)+1,t=s+1;
	for (int i=1; i<=k; i++)
	{
		int x; sc(x);
		add (s,x,1,0);
	}
	add (n*(B*2)+1,t,1e9,0);
	for (int o=0; o< B*2; o++)
	{
		add (o*n+1,(o+1)*n+1,1e9,0);
		for (int i=2; i<=n; i++)
			add (o*n+i,(o+1)*n+i,1e9,c);
	}
	while (m--)
	{
		int x,y; sc(x),sc(y);
		for (int o=0; o< B*2; o++)
		{
			for (int i=1; i<=k; i++)
				add (o*n+x,(o+1)*n+y,1,d*(2*i-1)+c),add (o*n+y,(o+1)*n+x,1,d*(2*i-1)+c);
		}
	}
	mcmf ();
	// pr(maflow);
	pr(micost);

    return 0;
}


#include<bits/stdc++.h>
using namespace std;
int n,m,r,c,d,occ[100];
pair<int,int>p[100];
namespace MCMF{
	const int N=10000,M=20000000;
	int head[N],cnt,dis[N],fr[N],id[N],S,T,cost;
	struct node{
		int to,next,val,cost;
	}edge[M];
	void ae(int u,int v,int w,int c){
		edge[cnt].cost=c,edge[cnt].next=head[u],edge[cnt].to=v,edge[cnt].val=w,head[u]=cnt++;
		edge[cnt].cost=-c,edge[cnt].next=head[v],edge[cnt].to=u,edge[cnt].val=0,head[v]=cnt++;
	}
	queue<int>q;
	bool in[N];
	bool SPFA(){
		memset(dis,0x3f,sizeof(dis)),dis[S]=0,q.push(S),in[S]=true;
		while(!q.empty()){
			int x=q.front();q.pop(),in[x]=false;
			for(int i=head[x];i!=-1;i=edge[i].next){
				if(!edge[i].val)continue;
				if(dis[edge[i].to]>dis[x]+edge[i].cost){
					dis[edge[i].to]=dis[x]+edge[i].cost,fr[edge[i].to]=x,id[edge[i].to]=i;
					if(!in[edge[i].to])in[edge[i].to]=true,q.push(edge[i].to);
				}
			}
		}
		if(dis[T]==dis[N-1])return false;
		int x=T,mn=0x3f3f3f3f;
		while(x!=S)mn=min(mn,edge[id[x]].val),x=fr[x];
		cost+=dis[T]*mn,x=T;
		while(x!=S)edge[id[x]].val-=mn,edge[id[x]^1].val+=mn,x=fr[x];
		return true;
	}
}
using namespace MCMF;
int main(){
	scanf("%d%d%d%d%d",&n,&m,&r,&c,&d),memset(head,-1,sizeof(head)),S=(r+n+1)*n+1,T=(r+n+1)*n+2;
	for(int i=1,x;i<=r;i++)scanf("%d",&x),occ[x]++;
	for(int i=1;i<=m;i++)scanf("%d%d",&p[i].first,&p[i].second);
	for(int i=0;i<r+n;i++)for(int j=1;j<=m;j++)for(int k=1;k<=r;k++)ae(i*n+p[j].first,(i+1)*n+p[j].second,1,(2*k-1)*d),ae(i*n+p[j].second,(i+1)*n+p[j].first,1,(2*k-1)*d);
	for(int i=1;i<=r+n;i++){
		ae(i*n+1,T,0x3f3f3f3f,i*c);
		for(int j=2;j<=n;j++)ae((i-1)*n+j,i*n+j,0x3f3f3f3f,0);
	}
	for(int i=1;i<=n;i++)ae(S,i,occ[i],0);
	while(SPFA());
	printf("%d\n",cost);
	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;
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;
        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(!vis[to[i]]){
                    vis[to[i]] = 1;
                    q.push(to[i]);
                }
            }
        }

    }
    return d[t] < inf;
}
int MinCostFlow(int s, int t){
    int Mi = inf;
    int sum = 0;
    int tt = 0;
    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;
    }
    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);
        //第一层时间点连接汇点，流量为100，费用为0
    for(int i = 1, v; i <= k; ++i){
        scanf("%d" , &v);
        add(s, (v-1)*100+1, 1, 0);
    }
    //将源点连接起始点的第一层时间点，流量为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);
        }
    }
    //每一层的时间点之间连边，流量为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 <= 20; ++k){
                add(idx, idy, 1, c + (k * k - (k-1) * (k-1))* d) ;
            }
           // 假设一条边同一时间只有20人经过，那么将一条边拓展成20条边，流量为1
           //费用为(k*k-(k-1)*(k-1))
        }
        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 <= 20; ++k){
                add(idx, idy, 1, c + (k * k - (k-1) * (k-1))* d) ;
            }
        }
        //将无向边拆成有向边
    }
    printf("%d\n", MinCostFlow(s, t));
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
typedef vector<int>vi;

#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define fi first
#define se second
#define de(x) cout<<#x<<"="<<x<<"\n"
#define dd(x) cout<<#x<<"="<<x<<" "
#define pb(x) push_back(x)
#define all(x) x.begin(),x.end()
#define sz(x) (int)x.size()
#define lowbit(a) ((a)&-(a))
#define per(i,a,b) for(int i=(b)-1;i>=(a);--i)
const int N=2e5+5;
const int inf= ~0U>>1;
template<class U,class V>
struct MCMF{
    static const int N = 30000, M = 7010010;
    int h[N], ing[N], pre[N], to[M], ne[M], e, s, t, n;
    U cap[M]; V dis[N], cost[M];
    void ini(int _n = N){ fill(h , h + (n=_n) , -1);e = 0;}
    void liu(int u,int v,U c,V w){ to[e] = v;ne[e] = h[u];cap[e] = c;cost[e] = w;h[u] = e++;}
    void link(int u,int v,U c,V w){ liu(u,v,c,w);liu(v,u,0,-w); }
    bool spfa(){
        queue<int> Q;
        fill(dis, dis+n, inf);
        Q.push(s), ing[s] = 1, dis[s] = 0;
        while(!Q.empty()){
            int c = Q.front(); Q.pop(); ing[c] = 0;
            for(int k = h[c]; ~k; k = ne[k]) if (cap[k] > 0) {
                int v = to[k];
                if(dis[c] + cost[k] < dis[v]){
                    dis[v] = dis[c] + cost[k];
                    pre[v] = k;
                    if(!ing[v]) Q.push(v) , ing[v] = 1;
                }
            }
        }
        return dis[t] != inf;
    }
    U flow; V mincost;
    pair<U, V> run(int _s,int _t){
        s = _s , t = _t;
        flow = mincost = 0;
        while(spfa()){
            U pl = inf; int p, k;
            for(p = t;p != s;p = to[k^1]) pl = min(pl, cap[k = pre[p]]);
            for(p = t;p != s;p = to[k^1]) cap[k = pre[p]] -= pl, cap[k^1] += pl;
			mincost += pl * dis[t];
            flow += pl;
        }
        return make_pair(flow, mincost);
    }
};
MCMF<int,int> flow;
int n , m , k ,c , d ,a[N] , id[55][2500];
int main(){
	scanf("%d%d%d%d%d",&n,&m,&k,&c,&d);
	rep(i , 1 , k + 1)
		scanf("%d",&a[i]);
	flow.ini(50*50*4 + 10);
	int s = flow.n - 2,t = flow.n - 3;
	int cnt = 0 ,mx = 100;
	rep(i , 1 , n + 1)
		rep(j , 0 , mx + 1)
			id[i][j] = ++cnt;
	int u , v;
	rep(i , 1 , m + 1){
		scanf("%d%d",&u,&v);
		rep(j , 0 , mx){
			rep(h , 1 , k + 1){
				int tmp = h*h*d - (h-1)*(h-1)*d;
				flow.link(id[u][j] , id[v][j + 1] , 1 , c + tmp);
				flow.link(id[v][j] , id[u][j + 1] , 1 , c + tmp);
			}
		}
	}
	rep(i , 1 , n + 1)
		rep(j , 0 , mx)
			flow.link(id[i][j] , id[i][j + 1] , inf , c);
	rep(i , 1 , k + 1)
		flow.link(s , id[a[i]][0] , 1 , 0);
	rep(j , 1 , mx + 1)flow.link(id[1][j] , t , inf , 0);
	int ans = flow.run(s , t).se;
	printf("%d\n",ans);
	return 0;
}


#include <bits/stdc++.h>
#define pb push_back
#define x first
#define y second

using namespace std;
typedef long long INT;
typedef pair <int, int> pii;
typedef vector <int> VI;

#define NN 6555
struct edge {
	int to, capacity, cost, rev;
	edge() {}
	edge(int to,int _capacity,int _cost,int _rev):
		to(to), capacity(_capacity), cost(_cost), rev(_rev) {}
};

const int inf=0x3f3f3f3f;

struct Min_Cost_Max_Flow {
	int V, H[NN + 5], dis[NN +5], PreV[NN +5], PreE[NN + 5];
	vector<edge> G[NN + 5];
	void Init(int n) {
		V = n;
		for (int i = 0; i <= V; ++i) G[i].clear();
   	}
	void add_edge(int from, int to, int cap, int cost) {
		G[from].push_back(edge(to, cap, cost, G[to].size()));
		G[to].push_back(edge(from,0, -cost, G[from].size() - 1));
	}
	int minCost(int s, int t, int f) {
		int flow = 0;
		int res = 0;
		fill(H, H +1 + V, 0);
		while (f) {
   			priority_queue <pii, vector<pii>, greater<pii> > q;
   			fill(dis, dis + 1 + V, inf);
   			dis[s] = 0; q.push(pii(0, s));
			while (!q.empty()) {
   				pii now = q.top(); q.pop();
				int v = now.second;
				if (dis[v] < now.first)continue;
				for (int i = 0; i < G[v].size(); ++i) {
   					edge& e = G[v][i];
					if (e.capacity > 0 && dis[e.to] > dis[v] + e.cost + H[v] - H[e.to]) {
   						dis[e.to] = dis[v] + e.cost + H[v] - H[e.to];
   						PreV[e.to] = v;
   						PreE[e.to] = i;
   						q.push(pii(dis[e.to], e.to));
	   				}
	   			}
	   		}
			if (dis[t] == inf)   break;
			for (int i = 0; i <= V; ++i)H[i] += dis[i];
			int d = f;
			for (int v = t; v != s; v = PreV[v])d = min(d, G[PreV[v]][PreE[v]].capacity);
   			f -= d; flow += d; res += d*H[t];
			for (int v = t; v != s; v = PreV[v]) {
   				edge& e = G[PreV[v]][PreE[v]];
   				e.capacity -= d;
   				G[v][e.rev].capacity += d;
			}
   		}
		return res;
   	}
} mcmf;

int main (){
#ifndef ONLINE_JUDGE
	freopen ("in.in", "r", stdin);
	freopen ("out.out", "w", stdout);
#endif

	int n, m, k, c, d;

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

	mcmf.Init(n*(n+55)+2);
	for(int i=0; i<k; i++){
		int u; cin >> u;
		mcmf.add_edge(0, u, 1, 0);
	}

	vector <pii> edge=vector <pii> (m);
	for(int i=0; i<m; i++) cin >> edge[i].x >> edge[i].y;

	int tar=n*(n+55)+1;
	for(int t=0; t<n+54; t++){
		for(pii e : edge){
			for(int j=1; j<=k; j++){
				mcmf.add_edge(e.x+t*n, e.y+(t+1)*n, 1, c+d*(j*2-1));
				mcmf.add_edge(e.y+t*n, e.x+(t+1)*n, 1, c+d*(j*2-1));
			}
		}
		for(int i=2; i<=n; i++){
			mcmf.add_edge(i+t*n, i+(t+1)*n, k, c);
		}
		mcmf.add_edge(1+t*n, tar, k, 0);
	}

	cout << mcmf.minCost(0, tar, k) << endl;

	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define DEBUG 0
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
#define fore(i,ii,iii) for(int i=ii;i<iii;i++)
#define pb push_back
#define SZ(a) ((int)(a).size())
#define mset(a,b) memset(a,b,sizeof(a));
#define ALL(a) a.begin(),a.end()
#define fst first
#define snd second

const int MAXN=50*100+15;
int SRC = MAXN-1;
int SNC = MAXN-2;

typedef ll tf;const tf INFFLUJO=1e14;
typedef ll tc;const tc INFCOSTO=1e14;
struct edge {
	int u,v;tf cap,flow;tc cost;
	tf rem(){return cap-flow;}
};
int nodes=MAXN; // remember to init nodes
vector<int> g[MAXN];
vector<edge> e;
void add_edge(int u, int v, tf cap, tc cost) {
	if(DEBUG) {
		string dem=to_string(u),pen=to_string(v);
		if(u==SRC)dem="SRC";
		if(u==SNC)dem="SINC";
		if(v==SRC)pen="SRC";
		if(v==SNC)pen="SINC";
		cout<<"add edge: "<<dem<<" "<<pen<<" "<<cap<<" "<<cost<<endl;
	}
	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});
}
tc dist[MAXN],mncost;
int pre[MAXN];
tf cap[MAXN],mxflow;
bool in_queue[MAXN];
void flow(int s, int t){
	memset(in_queue,0,sizeof(in_queue));
	mxflow=mncost=0;
	while(1){
		fill(dist,dist+nodes,INFCOSTO);dist[s]=0;
		memset(pre,-1,sizeof(pre));pre[s]=0;
		memset(cap,0,sizeof(cap));cap[s]=INFFLUJO;
		queue<int> q;q.push(s);in_queue[s]=1;
		while(SZ(q)){
			int u=q.front();q.pop();in_queue[u]=0;
			fore(_,0,SZ(g[u])){
				int i=g[u][_];
				edge &E=e[i];
				if(E.rem()&&dist[E.v]>dist[u]+E.cost+1e-9){
					dist[E.v]=dist[u]+E.cost;
					pre[E.v]=i;
					cap[E.v]=min(cap[u],E.rem());
					if(!in_queue[E.v])q.push(E.v),in_queue[E.v]=1;
				}
			}
		}
		if(pre[t]<0)break;
		mxflow+=cap[t];mncost+=cap[t]*dist[t];
		for(int v=t;v!=s;v=e[pre[v]].u){
			e[pre[v]].flow+=cap[t];e[pre[v]^1].flow-=cap[t];
		}
	}
}
int main() {
  ios::sync_with_stdio(false);
	ll n,m,k,c,d;
  cin>>n>>m>>k>>c>>d;
	int MAXT=n+k;
	if(DEBUG)cout<<"MAXT: "<<MAXT<<endl;
	vector<int>a(k);
	fore(i,0,k){
		cin>>a[i];a[i]--;
		add_edge(SRC,a[i]*MAXT,1,0);
	}
	fore(j,0,MAXT)add_edge(j,SNC,k,0);
	fore(i,0,m) {
		int x,y;cin>>x>>y;x--,y--;
		fore(j,0,MAXT-1)fore(K,1,k+1) {
			add_edge(x*MAXT+j,y*MAXT+j+1,1,c+d*(2*K-1));
		}
		fore(j,0,MAXT-1)fore(K,1,k+1) {
			add_edge(y*MAXT+j,x*MAXT+j+1,1,c+d*(2*K-1));
		}
	}
	fore(i,0,n) {
		fore(j,0,MAXT-1)fore(K,1,k+1) {
			add_edge(i*MAXT+j,i*MAXT+j+1,1,c);
		}
	}
	flow(SRC,SNC);
	if(DEBUG)cout<<"mncost: "<<mncost<<" mxflow: "<<mxflow<<endl;
	cout<<mncost<<endl;
}


#include <bits/stdc++.h>
using namespace std;
const int N = 10000010, INF = 0x3f3f3f3f;
int n, m, c, d, k, s = 0, t, ans = 0;
int cnt = 1, hed[N], to[N], nxt[N], val[N], w[N];
int dis[N], incf[N], pre[N]; bool inq[N];

void add(int x, int y, int z, int v) {
	to[++cnt] = y, nxt[cnt] = hed[x], hed[x] = cnt, val[cnt] = z, w[cnt] = v;
	to[++cnt] = x, nxt[cnt] = hed[y], hed[y] = cnt, val[cnt] = 0, w[cnt] = -v;
}
bool spfa() {
	memset(incf, 0, sizeof(incf)), memset(dis, INF, sizeof(dis));
	memset(inq, 0, sizeof(inq)); queue<int> q;
	q.push(s), incf[s] = INF, inq[s] = 1, dis[s] = 0;
	for(; !q.empty();) {
		int u = q.front(); q.pop(); inq[u] = 0;
		for(int i = hed[u]; i; i = nxt[i]) {
			if(!val[i] || dis[to[i]] <= dis[u] + w[i]) continue;
			dis[to[i]] = dis[u] + w[i];
			incf[to[i]] = min(incf[u], val[i]);
			pre[to[i]] = i; if(!inq[to[i]]) inq[to[i]] = 1, q.push(to[i]);
		}
	}
	return dis[t] != INF;
}
void update() {
	int tmp = t;
	for(; tmp != s;) {
		int i = pre[tmp];
		val[i] -= incf[t], val[i ^ 1] += incf[t], tmp = to[i ^ 1];
	}
	ans += incf[t] * dis[t];
}
int main() {
	scanf("%d%d%d%d%d", &n, &m, &k, &c, &d), t = (n + k - 1) * n + 1;
	for(int i = 1, x; i <= k; i++) scanf("%d", &x), add(s, x, 1, 0);
	for(int i = 1, x, y; i <= m; i++) {
		scanf("%d%d", &x, &y);
		for(int j = 1; j <= n + k; j++)
			for(int h = 1; h <= k; h++) {
				add(x + (j - 1) * n, y + j * n, 1, d * h * 2 - d + c);
				add(y + (j - 1) * n, x + j * n, 1, d * h * 2 - d + c);
			}
	}
	for(int i = 1; i < n + k; i++) {
		for(int j = 2; j <= n; j++)
			add(j + (i - 1) * n, j + i * n, INF, c);
		add(1 + (i - 1) * n, 1 + i * n, INF, 0);
	}
	for(; spfa();) update();
	printf("%d\n", ans);
	return 0;
}


#include <bits/stdc++.h>
#define db(x) cout << (x) << '\n';
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pii;
typedef pair<ll,pii> pip;
typedef pair<pii,pii> ppp;
typedef long double ld;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;

typedef tree<ll, null_type, less<ll>,rb_tree_tag, tree_order_statistics_node_update> ordered_set;

/*
    Minimum Cost Flow (Tomizawa, Edmonds-Karp)
    Complexity:
    O(F m log n), where F is the amount of maximum flow
    Tested:
    Codeforces [http://codeforces.com/problemset/problem/717/G]
*/
template<typename flow_type, typename cost_type>
struct min_cost_max_flow
{
    struct edge
    {
        size_t src, dst, rev;
        flow_type flow, cap;
        cost_type cost;
    };
    int n;
    vector<vector<edge>> adj;
    min_cost_max_flow(int n) : n(n), adj(n), potential(n), dist(n), back(n) {}
    void add_edge(size_t src, size_t dst, flow_type cap, cost_type cost)
    {
        adj[src].push_back({src, dst, adj[dst].size(), 0, cap, cost});
        if (src == dst)
            adj[src].back().rev++;
        adj[dst].push_back({dst, src, adj[src].size() - 1, 0, 0, -cost});
    }
    vector<cost_type> potential;
    inline cost_type rcost(const edge &e)
    {
        return e.cost + potential[e.src] - potential[e.dst];
    }

//    void bellman_ford(int source)
//    {
//        for (int k = 0; k < n; ++k)
//            for (int u = 0; u < n; ++u)
//                for (edge &e : adj[u])
//                    if (e.cap > 0 && rcost(e) < 0)
//                        potential[e.dst] += rcost(e);
//    }
    const cost_type oo = numeric_limits<cost_type>::max();
    vector<cost_type> dist;
    vector<edge * > back;
    cost_type dijkstra(int source, int sink)
    {
        fill(dist.begin(), dist.end(), oo);
        typedef pair<cost_type, int> node;
        priority_queue<node, vector<node>, greater<node>> pq;
        for (pq.push({dist[source] = 0, source}); !pq.empty();)
        {
            node p = pq.top();
            pq.pop();
            if (dist[p.second] < p.first)
                continue;
            if (p.second == sink)
                break;
            for (edge &e : adj[p.second])
                if (e.flow < e.cap &&
                        dist[e.dst] > dist[e.src] + rcost(e))
                {
                    back[e.dst] = &e;
                    pq.push({
                        dist[e.dst] = dist[e.src] + rcost(e),
                        e.dst
                    });
                }
        }
        return dist[sink];
    }
    pair<flow_type, cost_type> max_flow(int source, int sink)
    {
        flow_type flow = 0;
        cost_type cost = 0;
        for (int u = 0; u < n; ++u)
            for (edge &e : adj[u])
                e.flow = 0;
        potential.assign(n, 0);
        dist.assign(n, 0);
        back.assign(n, nullptr);
//        bellman_ford(source); // remove negative costs
        while (dijkstra(source, sink) < oo)
        {
            for (int u = 0; u < n; ++u)
            if (dist[u] < dist[sink])
                potential[u] += dist[u] - dist[sink];
            flow_type f = numeric_limits<flow_type>::max();
            for (edge * e = back[sink]; e; e = back[e->src])
                f = min(f, e->cap - e->flow);
            for (edge * e = back[sink]; e; e = back[e->src])
                e->flow += f, adj[e->dst][e->rev].flow -= f;
            flow += f;
            cost += f * (potential[sink] - potential[source]);
        }
        return {flow, cost};
    }
};

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n,m,k,c,d,u,v;
    cin >> n >> m >> k >> c >> d;
    min_cost_max_flow<int,int> g((n+2)*102);
    for(int i=0;i<102;i++)
        g.add_edge((i*(n+2))+1,i*(n+2),100,(i*c));
    for(int i=0;i<101;i++)
        for(int j=0;j<n+1;j++)
            g.add_edge(j+(i*(n+2)),j+((i+1)*(n+2)),100,0);
    for(int i=0;i<k;i++)
    {
        cin >> u;
        g.add_edge(n+1,u,1,0);
    }

    for(int i=0;i<m;i++)
    {
        cin >> u >> v;
        for(int j=0;j<101;j++)
            for(int f=0;f<k;f++)
            {
                g.add_edge(u+(j*(n+2)),v+((j+1)*(n+2)),1,((2*f)+1)*d);
                g.add_edge(v+(j*(n+2)),u+((j+1)*(n+2)),1,((2*f)+1)*d);
            }
    }

    db(g.max_flow(n+1,(101*(n+2))).second)

    return 0;
}


#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define N 100010
using namespace std;
typedef int typ;
#define M 1000010
#define inf 1000000000
#define winf 1000000000
struct road{
    int nxt,to,f;
    typ w;
}r[M<<1];
int head[N],cnt=1,all;
void add(int u,int v,int f,typ w)
{
    r[++cnt]=(road){head[u],v,f,w};head[u]=cnt;
    r[++cnt]=(road){head[v],u,0,-w};head[v]=cnt;
}
namespace min_cost_flow{
    int cur[N];
    bool vis[N];
    struct node{
        int u;typ v;
        node(int U=0,typ V=0):u(U),v(V){}
        bool operator <(const node a)const{return v>a.v;}
    };
    priority_queue<node>q;
    typ dis[N],tag[N];
    bool dij(int s,int t)
    {
        for(int i=1;i<=all;i++) dis[i]=winf,cur[i]=head[i];
        dis[t]=0;q.push(node(t,0));
        while(!q.empty())
        {
            int u=q.top().u;q.pop();
            if(vis[u]) continue;
            vis[u]=true;
            for(int i=head[u];i;i=r[i].nxt)
            {
                int v=r[i].to,w=tag[u]+r[i^1].w-tag[v];
                if(r[i^1].f && dis[u]+w<dis[v]) dis[v]=dis[u]+w,q.push(node(v,dis[v]));
            }
        }
        for(int i=1;i<=all;i++) tag[i]=min(tag[i]+dis[i],winf);
        if(!vis[s]) return false;
        for(int i=1;i<=all;i++) vis[i]=false;
        return true;
    }
    int dfs(int u,int t,int fl)
    {
        if(u==t || !fl) return fl;
        int res=0;
        vis[u]=true;
        for(int &i=cur[u];i;i=r[i].nxt)
        if(r[i].f)
        {
            int v=r[i].to,f;
            if(!vis[v] && tag[v]+r[i].w==tag[u] && (f=dfs(v,t,min(fl,r[i].f))))
            {
                r[i].f-=f,r[i^1].f+=f;
                res+=f,fl-=f;
                if(!fl) break;
            }
        }
        vis[u]=false;
        return res;
    }
    int maxf;typ minw;
    void work(int s,int t){while(dij(s,t)){int w=dfs(s,t,inf);maxf+=w,minw+=w*tag[s];}}
}
int ss=1,tt=2,n,m,k,c,d;
vector<int>g[N];
inline int id(int t,int x){return t*n+x+2;}
void work(int t)
{
    all+=n;
    for(int u=1;u<=n;u++)
        for(int v:g[u])
        {
            for(int p=1;p<=k;p++)
            add(id(t,u),id(t+1,v),1,d*(2*p-1));
        }
    for(int u=1;u<=n;u++) add(id(t,u),id(t+1,u),inf,0);
    add(id(t+1,1),tt,inf,c*(t+1));
}
int main()
{
    scanf("%d%d%d%d%d",&n,&m,&k,&c,&d);
    all=n+2;
    for(int i=1;i<=k;i++)
    {
        int a;
        scanf("%d",&a);
        add(ss,id(0,a),1,0);
    }
    for(int i=1;i<=m;i++)
    {
        int u,v;
        scanf("%d%d",&u,&v);
        g[u].push_back(v);g[v].push_back(u);
    }
    add(id(0,1),tt,inf,0);
    for(int i=0;i<=n+k;i++) work(i);
    min_cost_flow::work(ss,tt);
    printf("%d\n",min_cost_flow::minw);
    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) {
    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
      queue<int> dk; dk.push(s); while(!dk.empty()) {
        int u = dk.front(); 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(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;
}