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


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
//typedef long double ld;

const int maxn=5007;

//const ll INF = 1e18;
const ll INF =  1e9;
const ll mod = 1e9+7;

struct Edge {
    int from,to;
    ll cap, cost, flow;
    Edge(int from, int to, ll cap, ll cost): from(from), to(to), cap(cap), cost(cost), flow(0) {};
};

vector<Edge> edges;
ll d[maxn], phi[maxn];
vector<int> g[maxn];
int par[maxn];

void add_edge(int u, int v, ll cap, ll cost) {
    g[u].push_back(edges.size());
    edges.push_back({u,v,cap,cost});
    g[v].push_back(edges.size());
    edges.push_back({v,u,0,-cost});
}
void ford_bellman(int s, int n) {
    for (int i=0;i<maxn;i++) {
        phi[i] = INF;
    }
    phi[s] = 0;
    for (int i=0;i<n;i++) {
        for (int j=0;j<edges.size();j++) {
            if (edges[j].cap==edges[j].flow) continue;
            int from = edges[j].from;
            int to = edges[j].to;
            ll len = edges[j].cost;
            if (phi[from]==INF) continue;
            phi[to] = min(phi[to], phi[from]+len);
        }
    }
}

void dijkstra(int s) {
    for (int i=0;i<maxn;i++) {
        d[i] = INF;
    }
    d[s] = 0;
    set<pair<ll,int>> q;
    q.insert({0,s});
    while (!q.empty()) {
        int v = q.begin()->second;
        q.erase(q.begin());
        for (int i=0;i<g[v].size();i++) {
            int eid = g[v][i];
            if (edges[eid].cap==edges[eid].flow) continue;
            int to = edges[eid].to;
            ll len = edges[eid].cost + phi[v] - phi[to];
            if (d[v]+len<d[to]) {
                q.erase({d[to],to});
                d[to] = d[v]+len;
                par[to] = eid;
                q.insert({d[to],to});
            }
        }
    }
}

pair<ll,ll> mincost_maxflow(int s, int t) {
    ford_bellman(s, 50);
    dijkstra(s);
    ll flow = 0, cost = 0;
    while (1) {
        if (d[t]==INF) break;
        ll pushed=  INF, sum = 0;
        for (int tmp = t;tmp!=s;) {
//            if (tmp==100) {
//                cout << "xyu";
//            }
            int eid = par[tmp];
            pushed = min(pushed, edges[eid].cap-edges[eid].flow);
            sum+=edges[eid].cost;
            tmp = edges[eid].from;
        }
        flow+=pushed;
        cost+=pushed*sum;
        //cout << "flow: " << flow << ", cost: " << cost << endl <<  t << " ";
        for (int tmp=t;tmp!=s;) {
            int eid = par[tmp];
            edges[eid].flow+=pushed;
            edges[eid^1].flow-=pushed;
            tmp = edges[eid].from;
          //  cout << tmp << " ";
        }
        //cout << endl;

        dijkstra(s);
        for (int i=0;i<maxn;i++) {
            phi[i] = d[i];
        }
    }
    return {cost, flow};
}
void solve() {
    int n,m,k,c,d;
    cin >> n >> m >> k >> c >> d;
    vector<int> cnts(n,0);
    for (int i=0;i<k;i++) {
        int ai;
        cin >> ai;
        ai--;
        cnts[ai]++;
    }
    for (int i=0;i<n;i++) {
        add_edge(5000, i, cnts[i],0);
    }
    for (int it=0;it<m;it++) {
        int u,v;
        cin >> u >> v;
        u--; v--;
        for (int i=0;i<99;i++) {
            ll cost = d;
            for (int j=0;j<50;j++) {
                add_edge(u+i*50, v+(i+1)*50, 1, cost);
                add_edge(v+i*50, u+(i+1)*50, 1, cost);
                cost+=2*d;
            }
        }
    }
    for (int i=0;i<=99;i++) {
        add_edge(0+i*50, 5001, INF, c*i);
    }

    for (int i=0;i<n;i++) {
        for (int j=0;j<99;j++) {
            add_edge(i+j*50, i+(j+1)*50, INF, 0);
        }
    }
    //add_edge(0+99*50, 5001, INF, 0);

    auto p = mincost_maxflow(5000, 5001);
    assert(p.second==k);
    cout << p.first;
}
int main() {
    cin.tie(0);
    cout.tie(0);
    ios_base::sync_with_stdio(false);
    cout << setprecision(20) << fixed;
   // freopen("input.txt","r", stdin);
//    int t;
//    cin >> t;
//    for (int i=0;i<t;i++)
    solve();
    return 0;
}


// 费用流

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

const int MAXN = 10000;
const int MAXM = 2000000;
const int INF = 0x3f3f3f3f;

int n, m, k, c, d;

struct Edge
{
    int to, next, cap, flow, cost;
} edge[MAXM];
int head[MAXN], tol;
int pre[MAXN], dis[MAXN];
bool vis[MAXN];
int N; //节点总个数,节点编号从0~N-1
void init(int n)
{
    N = n;
    tol = 0;
    memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int cap, int cost)
{
    edge[tol].to = v;
    edge[tol].cap = cap;
    edge[tol].cost = cost;
    edge[tol].flow = 0;
    edge[tol].next = head[u];
    head[u] = tol++;
    edge[tol].to = u;
    edge[tol].cap = 0;
    edge[tol].cost = -cost;
    edge[tol].flow = 0;
    edge[tol].next = head[v];
    head[v] = tol++;
}
bool spfa(int s, int t)
{
    queue<int> q;
    for (int i = 0; i < N; i++)
    {
        dis[i] = INF;
        vis[i] = false;
        pre[i] = -1;
    }
    dis[s] = 0;
    vis[s] = true;
    q.push(s);
    while (!q.empty())
    {
        int u = q.front();
        q.pop();
        vis[u] = false;
        for (int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;

            if (edge[i].cap > edge[i].flow &&
                dis[v] > dis[u] + edge[i].cost)
            {
                dis[v] = dis[u] + edge[i].cost;
                pre[v] = i;
                if (!vis[v])
                {
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
    if (pre[t] == -1)
        return false;
    else
        return true;
}
//返回的是最大流,cost存的是最小费用
int minCostMaxflow(int s, int t, int &cost)
{
    int flow = 0;
    cost = 0;
    while (spfa(s, t))
    {
        int Min = INF;
        for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to])
        {
            if (Min > edge[i].cap - edge[i].flow)
                Min = edge[i].cap - edge[i].flow;
        }
        for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to])
        {
            edge[i].flow += Min;
            edge[i ^ 1].flow -= Min;
            cost += edge[i].cost * Min;
        }
        flow += Min;
    }
    return flow;
}

int main()
{
    cin >> n >> m >> k >> c >> d;
    init(MAXN);
    for(int i = 0; i < k; i++)
    {
        int x;
        cin >> x;
        addedge(0, x, 1, 0);
    }
    for(int i = 0; i < 100; i++)
    {
        for(int j = 0; j < k; j++)
            addedge(1+i*n, 9999, 1, i*c);
    }
    for(int i = 0; i < m; i++)
    {
        int u, v;
        cin >> u >> v;
        for(int j = 1; j < 100; j++)
        {
            for(int gg = 1; gg <= k; gg++)
            {
                addedge(u+(j-1)*n, v+j*n, 1, (2*gg-1)*d);
                addedge(v+(j-1)*n, u+j*n, 1, (2*gg-1)*d);
            }
        }
    }
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j < 100; j++)
        {
            addedge(i+(j-1)*n, i+j*n, k, 0);
        }
    }

    int cost;
    minCostMaxflow(0, 9999, cost);
    cout << cost << endl;
}

/*
3 2 4 2 3
3 3 3 3
1 2
2 3
 */


/* upsolve with Dukkha */
#include <stdio.h>
#include <string.h>

#define N	50
#define M	50
#define K	50
#define T	(N + K + 1)
#define N_	(N * T + 1)
#define M_	(K + (M * 2 * K + N) * (T - 1))
#define INF	0x3f3f3f3f

#define LT(u, v)	(pi[u] < pi[v] || pi[u] == pi[v] && kk[u] < kk[v])

int pi[N_], kk[N_], bb[N_];
int pq[1 + N_], iq[N_], cnt;

int i2(int i) {
	return (i *= 2) > cnt ? 0 : i < cnt && LT(pq[i + 1], pq[i]) ? i + 1 : i;
}

void pq_up(int u) {
	int i, j;

	for (i = iq[u]; (j = i / 2) && LT(u, pq[j]); i = j)
		pq[iq[pq[j]] = i] = pq[j];
	pq[iq[u] = i] = u;
}

void pq_dn(int u) {
	int i, j;

	for (i = iq[u]; (j = i2(i)) && LT(pq[j], u); i = j)
		pq[iq[pq[j]] = i] = pq[j];
	pq[iq[u] = i] = u;
}

void pq_add(int u) {
	iq[u] = ++cnt;
	pq_up(u);
}

int pq_remove_first() {
	int u = pq[1], v = pq[cnt--];

	iq[v] = 1;
	pq_dn(v);
	return u;
}

struct L {
	struct L *next;
	int j;
} aa[N], aa_[N_];

void add(int i, int j) {
	static struct L l91[M * 2], *l = l91;

	l->j = j;
	l->next = aa[i].next; aa[i].next = l++;
}

void add_(int i, int h) {
	static struct L l91[M_ * 2], *l = l91;

	l->j = h;
	l->next = aa_[i].next; aa_[i].next = l++;
}

int n_, m_;
int uu[M_], vv[M_], uv[M_], cost[M_], cost_[M_];
int cc[M_ * 2];

void link(int u, int v, int cap, int cos) {
	int h = m_++;

	uu[h] = u, vv[h] = v, uv[h] = u ^ v;
	cost[h] = cos;
	cc[h << 1 ^ 0] = cap;
	add_(u, h << 1 ^ 0);
	add_(v, h << 1 ^ 1);
}

void dijkstra(int s) {
	memset(pi, 0x3f, n_ * sizeof *pi);
	pi[s] = 0;
	pq_add(s);
	while (cnt) {
		struct L *l;
		int u = pq_remove_first(), v;
		int h, h_, p, k = kk[u] + 1;

		for (l = aa_[u].next; l; l = l->next)
			if (cc[h_ = l->j]) {
				h = h_ >> 1;
				p = pi[u] + ((h_ & 1) == 0 ? cost_[h] : -cost_[h]);
				v = u ^ uv[h];
				if (pi[v] == INF) {
					pi[v] = p;
					kk[v] = k;
					bb[v] = h_;
					pq_add(v);
				} else if (pi[v] > p || pi[v] == p && kk[v] > k) {
					pi[v] = p;
					kk[v] = k;
					bb[v] = h_;
					pq_up(v);
				}
			}
	}
}

void push(int s, int t) {
#if 0
	int u, h, h_, c = INF;

	for (u = t; u != s; u ^= uv[h]) {
		h = (h_ = bb[u]) >> 1;
		if (c > cc[h_])
			c = cc[h_];
	}
	for (u = t; u != s; u ^= uv[h]) {
		h = (h_ = bb[u]) >> 1;
		cc[h_] -= c, cc[h_ ^ 1] += c;
	}
#else
	int u, h, h_;

	for (u = t; u != s; u ^= uv[h]) {
		h = (h_ = bb[u]) >> 1;
		cc[h_]--, cc[h_ ^ 1]++;
	}
#endif
}

int edmonds_karp(int s, int t) {
	int c, h;

	memcpy(cost_, cost, m_ * sizeof *cost);
	while (1) {
		dijkstra(s);
		if (pi[t] == INF)
			break;
		push(s, t);
		for (h = 0; h < m_; h++) {
			int u = uu[h], v = vv[h];

			if (pi[u] != INF && pi[v] != INF)
				cost_[h] += pi[u] - pi[v];
		}
	}
	c = 0;
	for (h = 0; h < m_; h++)
		c += cost[h] * cc[h << 1 ^ 1];
	return c;
}

int main() {
	static int ii[K];
	int n, m, k, t, c, d, h, i, j, s, u, v, x;

	scanf("%d%d%d%d%d", &n, &m, &k, &c, &d);
	for (h = 0; h < k; h++)
		scanf("%d", &ii[h]), ii[h]--;
	while (m--) {
		scanf("%d%d", &i, &j), i--, j--;
		add(i, j), add(j, i);
	}
	t = n + k + 1;
	n_ = n * t + 1;
	m_ = 0;
	for (i = 0; i < n; i++)
		for (s = 0; s < t - 1; s++) {
			struct L *l;

			u = i * t + s;
			for (l = aa[i].next; l; l = l->next) {
				j = l->j;
				v = j * t + s + 1;
				for (x = 1; x <= k; x++)
					link(u, v, 1, c + (x * 2 - 1) * d);
			}
		}
	for (i = 0; i < n; i++)
		for (s = 0; s < t - 1; s++) {
			u = i * t + s, v = u + 1;
			link(u, v, k, i == 0 ? 0 : c);
		}
	for (h = 0; h < k; h++)
		link(n_ - 1, ii[h] * t + 0, 1, 0);
	printf("%d\n", edmonds_karp(n_ - 1, 0 * t + t - 1));
	return 0;
}


#include <bits/stdc++.h>
//
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxm = 2000015;
const int maxn = 105*55;
int n, m, c, d, k;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
struct Edge
{
    int to, next, cap, flow, cost;
}edge[maxm];
int head[maxn], tol;
int pre[maxn], dis[maxn];
bool vis[maxn];
int N ;
void init(int n)
{
    N = n;
    tol = 0;
    memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int cap, int cost)
{
    edge[tol].to = v;
    edge[tol].cap = cap;
    edge[tol].cost = cost;
    edge[tol].flow = 0;
    edge[tol].next = head[u];
    head[u] = tol++;
    edge[tol].to = u;
    edge[tol].cap = 0;
    edge[tol].cost = -cost;
    edge[tol].flow = 0;
    edge[tol].next = head[v];
    head[v] = tol++;
}
bool spfa(int s, int t)
{
    queue<int>q;
    for(int i = 0; i < N; i++)
    {
        dis[i] = INF;
        vis[i] = false;
        pre[i] = -1;
    }
    dis[s] = 0;
    vis[s] = true;
    q.push(s);
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        vis[u] = false;
        for(int i = head[u]; i != -1; i = edge[i].next)
        {
            int v = edge[i].to;
            if(edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost)
            {
                dis[v] = dis[u] + edge[i].cost;
                pre[v] = i;
                if(!vis[v])
                {
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
    if(pre[t] == -1) return false;
    else return true;
}
int minCostMaxflow(int s, int t, int &cost)
{
    int flow = 0;
    cost = 0;
    while(spfa(s,t))
    {
        int Min = INF;
        for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
        {
            if(Min > edge[i].cap - edge[i].flow)
                Min = edge[i].cap - edge[i].flow;
        }
        for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
        {
            edge[i].flow += Min;
            edge[i^1].flow -= Min;
            cost +=  edge[i].cost*Min;
        }
        flow += Min;
    }
    return flow;
}
int point(int x, int y){
    return (x-1)*50+y;
}
int main(){
    int S = 101*55, T = S + 1;
    n = read(), m = read(), k = read(), c = read(), d = read();
    int tmp;
    init(T+1);
    for(int i = 1; i <= k; i++){
        tmp = read();
        addedge(S, tmp, 1, 0);
    }
    for(int i = 1; i <= 50; i++){
        for(int j = 1; j <= 103; j++){
            int x = point(j, i);
            int y = point(j+1, i);
            addedge(x, y, INF, c);
        }
    }
    for(int i = 0; i < 102; i++){
        int tmp = i*50+1;
        addedge(tmp, T, INF, 0);
    }
    for(int i = 1; i <= m; i++){
        int u, v;
        u = read(), v = read();
        for(int j = 1; j <= 102; j++){
            int x = point(j, u), x1 = point(j+1, u);
            int y1 = point(j+1, v), y = point(j, v);
            for(int k = 0; k < 50; k++){
                int val = d*(k*2+1)+c;
                addedge(x, y1, 1, val);
                addedge(y, x1, 1, val);
            }
        }
    }
    int cost = 0;
    minCostMaxflow(S, T, cost);
    cout << cost << endl;
    return 0;
}


#include<bits/stdc++.h>
#define L(i, j, k) for(int i = j, i##E = k; i <= i##E; i++)
#define R(i, j, k) for(int i = j, i##E = k; i >= i##E; i--)
#define ll long long
#define db double
#define pii pair<int, int>
#define mkp make_pair
#define se second
#define fi first
using namespace std;
const int N = 5005;
const int M = 4 * N * sqrt(N);
const int inf = 1e9;
struct cf { int c, f; };
int n, m, k, c, d, s, t, tot, pre[N];
int head[N], edge_id = 1;
struct node {
	int to, next, val, w;
} e[M << 1];
void add_edge(int u, int v, int val, int w) {
	++edge_id, e[edge_id].next = head[u], e[edge_id].w = w, e[edge_id].to = v, e[edge_id].val = val, head[u] = edge_id;
}
void add(int u, int v, int val, int w) {
	add_edge(u, v, val, w), add_edge(v, u, 0, -w);
}
int dis[N]; bool vis[N];
bool SPFA() {
	fill(dis + 1, dis + tot + 1, inf);
	queue<int> q;
	q.push(s), dis[s] = 0;
	while(!q.empty()) {
		int u = q.front();
		vis[u] = 0;
		q.pop();
		for(int i = head[u]; i; i = e[i].next) {
			int v = e[i].to;
			if(e[i].val && dis[v] > dis[u] + e[i].w) {
				dis[v] = dis[u] + e[i].w, pre[v] = i;
				if(!vis[v]) vis[v] = 1, q.push(v);
			}
		}
	}
	return dis[t] < inf;
}
cf mcmf() {
	cf res = {};
	while(SPFA()) {
		int flow = inf;
		for(int x = t; x != s; x = e[pre[x] ^ 1].to) flow = min(flow, e[pre[x]].val);
		for(int x = t; x != s; x = e[pre[x] ^ 1].to) e[pre[x]].val -= flow, e[pre[x] ^ 1].val += flow;
		res.f += flow, res.c += dis[t] * flow;
	}
	return res;
}
#define P(i, j) ((i) * n + (j))
int E[N][2];
int main() {
	scanf("%d%d%d%d%d", &n, &m, &k, &c, &d);
	int cs = 2 * k; tot = cs * n;
	s = ++tot, t = ++tot;
	int tp; L(i, 1, k) scanf("%d", &tp), add(s, P(0, tp), 1, 0);
	L(i, 1, m) scanf("%d%d", &E[i][0], &E[i][1]);
	L(i, 1, cs - 1) {
		add(P(i, 1), t, k, c * i);
		L(j, 1, n) add(P(i - 1, j), P(i, j), k, 0);
		L(j, 1, m) L(t, 1, k)
			add(P(i - 1, E[j][0]), P(i, E[j][1]), 1, (2 * t - 1) * d),
			add(P(i - 1, E[j][1]), P(i, E[j][0]), 1, (2 * t - 1) * d);
	}
	printf("%d\n", mcmf().c);
	return 0;
}


#include <bits/stdc++.h>

using namespace std;
using ll = long long;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

const int inf = 1e9;
int n, m, k, c, d;
const int N = 4 * 55 * 105 * 105;

int mn[55 * 105][55 * 105];
int id[55 * 105][55 * 105];
int cnt[55 * 105];
struct MCMF {
    int n, m;
    void init(int _N) {
        n = _N;
        m = 0;
    }
    int S[N], E[N], F[N], C[N];
    void add_edge(int s, int e, int c) {
        S[m] = s;
        E[m] = e;
        F[m] = 0;
        C[m] = c;
        m++;
    }
    int solve(int st, int ed) {
        int ans = 0;
        for (int it = 1; it <= k; it++) {
            vector<vector<int>> edge(n);
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    mn[i][j] = inf;
                }
            }
            for (int i = 0; i < m; i++) {
                if (F[i]) {
                    mn[E[i]][S[i]] = min(mn[E[i]][S[i]], -C[i]);
                    if (mn[E[i]][S[i]] == -C[i]) id[E[i]][S[i]] = ~i;
                    edge[E[i]].push_back(S[i]);
                }
                else {
                    mn[S[i]][E[i]] = min(mn[S[i]][E[i]], C[i]);
                    if (mn[S[i]][E[i]] == C[i]) id[S[i]][E[i]] = i;
                    edge[S[i]].push_back(E[i]);
                }
            }
            for (int i = 0; i < n; i++) {
                vector<int> nw;
                for (int j : edge[i]) {
                    if (cnt[j]++ == 0) nw.push_back(j);
                }
                edge[i] = nw;
                for (int j : edge[i]) {
                    cnt[j] = 0;
                }
            }
            vector<int> D(n, inf);
            vector<int> P(n, 0);
            D[st] = 0;
            int loop = 1;
            while (loop) {
                loop = 0;
                for (int i = 0; i < n; i++) {
                    for (int j : edge[i]) {
                        if (mn[i][j] < inf && D[i] + mn[i][j] < D[j]) {
                            D[j] = D[i] + mn[i][j];
                            P[j] = i;
                            loop = 1;
                        }
                    }
                }
            }
            fflush(stdout);
            ans += D[ed];
            for (int x = ed; x != st; x = P[x]) {
                int p = P[x];
                if (id[p][x] < 0) {
                    int idx = ~id[p][x];
                    F[idx] = 0;
                }
                else {
                    int idx = id[p][x];
                    F[idx] = 1;
                }
            }
        }
        return ans;
    }
} F;

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m >> k >> c >> d;
    F.init(105 * n + 5);
    int ed = 105 * n + 4;
    for (int i = 0; i < k; i++) {
        int a;
        cin >> a;
        F.add_edge(0, a, 0);
    }
    for (int i = 0; i < 104; i++) {
        for (int j = 0; j < 105; j++)
            F.add_edge(1 + i * n, ed, 0);
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j < 104; j++) {
            for (int k = 0; k < 105; k++) {
                F.add_edge(i + (j - 1) * n, i + j * n, c);
            }
        }
    }
    for (int i = 0; i < m; i++) {
        int x, y;
        cin >> x >> y;
        for (int j = 1; j < 104; j++) {
            for (int k = 0; k < 105; k++) {
                F.add_edge(x + (j - 1) * n, y + j * n, c + (2 * k + 1) * d);
                F.add_edge(y + (j - 1) * n, x + j * n, c + (2 * k + 1) * d);
            }
        }
    }
    cout << F.solve(0, ed);
    return 0;
}


// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define mp make_pair
#define inf 100000000
#define nn 6000
namespace mcmf{
	vector<int> v[nn],rev[nn],cost[nn],cap[nn];
	void add_edge(int x,int y,int c,int w)
	{
		rev[x].push_back(v[y].size());rev[y].push_back(v[x].size());
		v[x].push_back(y);v[y].push_back(x);
		cost[x].push_back(w);cost[y].push_back(-w);
		cap[x].push_back(c);cap[y].push_back(0);
	}

	int dist[nn];int vis[nn];
	int prex[nn],prei[nn];
	void spfa(int s)
	{
		memset(dist,0x3f,sizeof dist);
		memset(vis,0,sizeof vis);prex[s]=-1;
		queue<int> q;q.push(s);dist[s]=0;vis[s]=1;

		while(q.size())
		{
			int x=q.front();q.pop();vis[x]=0;
			for(int i=0;i<v[x].size();i++)
			{
				int y=v[x][i];
				int cc=dist[x]+cost[x][i];
				if(dist[y]>cc and cap[x][i])
				{
					dist[y]=cc;prex[y]=x,prei[y]=i;
					if(!vis[y]) vis[y]=1,q.push(y);
				}
			}
		}

	}

	int tot=0;
	int dfs(int x,int flow)
	{
		if(prex[x]==-1) return flow;
		int y=x;x=prex[y];int i=prei[y],j=rev[x][i];
		int f=dfs(x,min(flow,cap[x][i]));
		cap[x][i]-=f,cap[y][j]+=f;
		return f;
	}

	pii solve(int s,int t)
	{
		int ans=0;tot=0;
		while(1)
		{
			spfa(s);
			if(dist[t]>1e9) break;
			int f=dfs(t,inf);
			tot+=f*dist[t];
			ans+=f;
		}
		return mp(ans,tot);
	}

};

int n,m,s=nn-1,t=nn-2;
int k,c,d;
int get(int x,int tim){
	return tim*52-52+x;
}
int main()
{
	scanf("%d%d%d%d%d",&n,&m,&k,&c,&d);int kk=k;
	while(k--){
		int x;scanf("%d",&x);
		mcmf::add_edge(s,get(x,1),1,0);
	}k=kk;
	while(m--){
		int x,y;scanf("%d%d",&x,&y);
		for(int i=1;i<100;i++)
			for(int j=1;j<=k;j++) mcmf::add_edge(get(x,i),get(y,i+1),1,d*(j+j-1));

		swap(x,y);
		for(int i=1;i<100;i++)
			for(int j=1;j<=k;j++) mcmf::add_edge(get(x,i),get(y,i+1),1,d*(j+j-1));
	}
	for(int i=1;i<100;i++){
		for(int j=1;j<=n;j++) mcmf::add_edge(get(j,i),get(j,i+1),inf,0);
		mcmf::add_edge(get(1,i),t,inf,c*(i-1));
	}

	printf("%d",mcmf::solve(s,t).second);

	return 0;
}


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

const int maxn = 5005;
typedef int T;
const T INF = 1e9+7;
const int K = 100;

struct Edge {
    int  u , v ;
    T cap ,flow , cost;
};

struct MCMF {
    int n,m,s,t;      // Total Number of Node Including S,T
    vector<int> G[maxn];     //Graph
    vector<Edge> E;         // EdgeList
    T d[maxn];             // Distance Array of BeTmanFord
    bool inq[maxn];           // Is node in queue
    int p[maxn];
    T a[maxn];

    MCMF(int n) : n(n) {}

    void addEdge( int u , int v , T cap , T cost ){
//        cout<<u<<" "<<v<<" "<<cap<<"/"<<cost<<endl;
        E.push_back({u, v , cap , 0 , cost});       // Positive Cost
        E.push_back({v,u , 0, 0 , -cost } );        // Negative Cost
        m = (int) E.size();
        G[u].push_back(m - 2);
        G[v].push_back(m - 1);
    }

    bool BelmanFord(T &flow , T &cost ) {
        for(int i = 0; i < n ;i  ++) d[i] = INF ;
        memset(inq, 0, sizeof(inq));
        d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;

        queue<int> Q;
        Q.push(s);
        while(!Q.empty() ) {
            int u = Q.front(); Q.pop();
            inq[u] = 0;

            for( int i = 0 ; i < G[u].size() ; i ++ ) {
                Edge &e = E[G[u][i]];
                if( e.cap > e.flow && d[e.v] > d[u] + e.cost ) {
                    d[e.v] = d[u] + e.cost;
                    p[e.v] = G[u][i];
                    a[e.v] = min( a[u] , e.cap - e.flow );

                    if( inq[e.v ] == 0 ) {
                        Q.push(e.v);
                        inq[e.v] = 1;
                    }
                }
            }
        }

        if( d[t] == INF ) return false;     // No augmenting Path
        flow = a[t];
        cost = d[t] ;               // Unit cost
        int u = t ;
        while( u  != s ) {
            E[p[u]].flow += a[t];
            E[p[u]^1].flow -= a[t];
            u = E[p[u]].u;
        }
        return true;
    }

    pair<T,T> Mincost (int s, int t) {
        this->s=s,this->t=t;
        T Mcost = 0;
        T Flow = 0;
        T f = 0 ;    // For Each CaT , The flow
        T d = 0;      // Shortest Distance / Cost Per Flow

        while(BelmanFord(f,d)) {
            Flow += f;
            Mcost += f *d ;
        }
        return make_pair(Flow, Mcost);
    }
};

int main() {
    int n, m, k, C, D;
    cin>>n>>m>>k>>C>>D;

    MCMF solver(n*K+2);
    int source = n*K, sink = n*K+1;

    for (int i=0; i<K; i++)
        solver.addEdge(i, sink, k, C*i);

    for (int i=0; i<k; i++) {
        int x;
        cin>>x;
        x--;
        solver.addEdge(source, x*K, 1, 0);
    }

    for (int i=0; i<n; i++)
        for (int j=1; j<K; j++)
            solver.addEdge(i*K+j-1, i*K+j, k, 0);

    while (m--) {
        int u, v;
        cin>>u>>v;
        u--; v--;

        for (int j=1; j<K; j++) {
            int a = u*K+j-1, b = v*K+j;
            int c = v*K+j-1, d = u*K+j;

            for (int i=1, cc = D; i<=k; i++, cc += 2*D) {
                solver.addEdge(a, b, 1, cc);
                solver.addEdge(c, d, 1, cc);
            }
        }
    }
    auto pr = solver.Mincost(source, sink);
    cout<<pr.second<<endl;
}


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

#define double long double
#define vec vector
#define pb push_back
#define unset unordered_set
#define ii pair<int, int>
#define X first
#define Y second
#define FOR(i, a, b) for(int i = (a); i < (b); i++)
#define FORE(i, a, b) for(int i = (a); i <= (b); i++)
#define FORD(i, a, b) for(int i = (a); i >= (b); i--)
#define bitcount(n) __builtin_popcountll(n)
template <typename T,typename U>
std::pair<T,U> operator+(const std::pair<T,U> & l,const std::pair<T,U> & r) {
  return {l.first+r.first,l.second+r.second};
}
typedef void (*callback_function)(void); // type for conciseness
const long long ZERO = 0LL;
const long long INF64 = 1e18;
const int INF32 = 1e9;
const int MOD = 1e9 + 7;
const double PI = acos(-1.0L);
const double EPS = static_cast<double>(1e-9);
typedef long long ll;

int norm(int a) {
  return ((a % MOD) + MOD) % MOD;
}

int mul(int a, int b) {
  return int(a * 1LL * b % MOD);
}

int binPow(int a, int k) {
  int ans = 1;
  for (; k > 0; k >>= 1) {
    if (k & 1) {
      ans = mul(ans, a);
    }
    a = mul(a, a);
  }
  return ans;
}

// If I need to find (x / a) % MOD, I need to use this function:
//    (x / a) % MOD = (x * inv(a)) % MOD
int inv(int a) {
  int b = binPow(a, MOD - 2);
  assert(mul(a, b) == 1);
  return b;
}

struct Edge {
  int y;
  int capacity;
  int flow;
  int cost;

  Edge() {};

  Edge(int _y, int _capacity, int _flow, int _cost)
    : y(_y), capacity(_capacity), flow(_flow), cost(_cost) {};
};

vec<Edge> e;

const int N = 1e6 + 7;
vec<int> g[N];

ll ans = 0;
ll dist[N];
int pred[N];
int pe[N];
int inq[N];

int source = N - 2;
int target = N - 1;

int residualCapacity(int x) {
  return e[x].capacity - e[x].flow;
}

void pushFlow() {
  FOR(i, 0, N) {
    dist[i] = INF64;
    pred[i] = -1;
    pe[i] = -1;
    inq[i] = 0;
  }
  dist[source] = 0;
  queue<int> q;
  q.push(source);
  inq[source] = 1;
  while (!q.empty()) {
    int k = q.front(); q.pop();
    inq[k] = 0;
    for (auto x : g[k]) {
      if (!residualCapacity(x)) {
        continue;
      }
      int cost = e[x].cost;
      int y = e[x].y;
      if (dist[y] > dist[k] + cost) {
        dist[y] = dist[k] + cost;
        pred[y] = k;
        pe[y] = x;
        if (inq[y] == 0) {
          inq[y] = 1;
          q.push(y);
        }
      }
    }
  }
  int cur = target;
  //vec<int> zz(1, cur);
  while (cur != source) {
    e[pe[cur]].flow++;
    e[pe[cur] ^ 1].flow--;
    cur = pred[cur];
    //zz.push_back(cur);
  }
  //reverse(zz.begin(), zz.end());
  //for (auto x : zz) {cerr << x << " ";}
  //cerr << "\n";
  ans += dist[target];
}

void addEdge(int x, int y, int capacity, int cost) {
  g[x].push_back(e.size());
  e.push_back(Edge(y, capacity, 0, cost));
  g[y].push_back(e.size());
  e.push_back(Edge(x, 0, 0, -cost));
}

int n, m, k, c, d;

void input() {
  //freopen("??.in", "r", stdin);
  //freopen("??.out", "w", stdout);
  scanf("%d %d %d %d %d", &n, &m, &k, &c, &d);
  FOR(i, 0, k) {
    int x;
    scanf("%d", &x);
    --x;
    addEdge(source, x, 1, 0);
  }
  int timeLayers = 101;
  FOR(i, 0, timeLayers) {
    addEdge(i * n, target, k, i * c);
  }
  FOR(i, 0, m) {
    int x, y;
    scanf("%d %d", &x, &y);
    --x, --y;
    FOR(i, 0, timeLayers - 1) FOR(j, 0, k) {
      addEdge(x + i * n, y + i * n + n, 1, d * (j * 2 + 1));
    }
    FOR(i, 0, timeLayers - 1) FOR(j, 0, k) {
      addEdge(y + i * n, x + i * n + n, 1, d * (j * 2 + 1));
    }
  }
  FOR(i, 0, n) FOR(j, 0, timeLayers - 1) {
    addEdge(i + j * n, i + j * n + n, k, 0);
  }
  FOR(i, 0, k) {
    pushFlow();
  }
  printf("%lld\n", ans);
}

void solve() {

  // read the question correctly (is y a vowel?)
  // look out for SPECIAL CASES (n=1?) and overflow (ll vs int?)
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie();
  //auto beginProgram = chrono::steady_clock::now();
  {
    input();
    solve();
  }
  //auto endProgram = chrono::steady_clock::now();

  return 0;
}


/*{{{*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<iostream>
#include<sstream>
#include<set>
#include<map>
#include<queue>
#include<bitset>
#include<vector>
#include<limits.h>
#include<assert.h>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define REP(I, N) for (int I = 0; I < (N); ++I)
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)
#define FOR(I, A, B) for (int I = (A); I <= (B); ++I)
#define FORS(I, S) for (int I = 0; S[I]; ++I)
#define RS(X) scanf("%s", (X))
#define SORT_UNIQUE(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define GET_POS(c,x) (lower_bound(c.begin(),c.end(),x)-c.begin())
#define CASET int ___T; scanf("%d", &___T); for(int cs=1;cs<=___T;cs++)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<PII> VPII;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;
template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(LL &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
template<class T> void _W(const T &x) { cout << x; }
void _W(const int &x) { printf("%d", x); }
void _W(const LL &x) { printf("%lld", x); }
void _W(const double &x) { printf("%.16f", x); }
void _W(const char &x) { putchar(x); }
void _W(const char *x) { printf("%s", x); }
template<class T,class U> void _W(const pair<T,U> &x) {_W(x.F); putchar(' '); _W(x.S);}
template<class T> void _W(const vector<T> &x) { for (auto i = x.begin(); i != x.end(); _W(*i++)) if (i != x.cbegin()) putchar(' '); }
void W() {}
template<class T, class... U> void W(const T &head, const U &... tail) { _W(head); putchar(sizeof...(tail) ? ' ' : '\n'); W(tail...); }
#ifdef HOME
 #define DEBUG(...) {printf("# ");printf(__VA_ARGS__);puts("");}
#else
 #define DEBUG(...)
#endif
int MOD = 1e9+7;
void ADD(LL& x,LL v){x=(x+v)%MOD;if(x<0)x+=MOD;}
/*}}}*/
const int SIZE = 1e6+10;
#define INF 1034567890
const int MAX_EDGE_NUM = 1000000;
const int MAX_NODE_NUM = 100000;
struct EDGE{
        int y,c,v,ty;
        EDGE(int _y=0,int _c=0,int _v=0,int ty=0):y(_y),c(_c),v(_v),ty(ty){}
}es[MAX_EDGE_NUM];
vector<int>e[MAX_NODE_NUM];
int C,d;
int en;
int EE; // sink
void flow_clear(int _EE){
    EE=_EE;
    REP(i,EE+1)e[i].clear();
    en=0;
}
void add_edge(int x,int y,int c,int v,int _ty){
        e[x].PB(en);
        es[en++]=EDGE(y,c,v,_ty);
        e[y].PB(en);
        if(_ty==1){
            es[en++]=EDGE(x,0,-C+d,_ty);
        }
        else{
            es[en++]=EDGE(x,0,-v,_ty);
        }

}
int mi[MAX_NODE_NUM],lt[MAX_NODE_NUM],bfs[10000000],used[MAX_NODE_NUM];
int flow(){
        REP(i,EE+1)mi[i]=INF,used[i]=0;
        mi[EE]=INF;
        bfs[0]=0;
        mi[0]=0;
        int rr=1;
        for(int i=0;i<rr;i++){
                int x=bfs[i];
                used[x]=0;
                REP(j,SZ(e[x])){
                        int r=e[x][j];
                        if(es[r].c>0&&mi[x]+es[r].v<mi[es[r].y]){
                                mi[es[r].y]=mi[x]+es[r].v;
                                lt[es[r].y]=r;
                                if(!used[es[r].y]){
                                        used[es[r].y]=1;
                                        bfs[rr++]=es[r].y;
                                }
                        }
                }
        }
        if(mi[EE]==INF)return -1;
        int now=EE;
        while(now){
                int r=lt[now];
                if(es[r].ty==1){
                    if((r&1)==1){
                        es[r].v+=2*d;
                        es[r^1].v-=2*d;
                    }
                    else{
                        es[r].v+=2*d;
                        es[r^1].v-=2*d;
                    }
                }
                es[r].c--;
                es[r^1].c++;
                now=es[r^1].y;
        }
        return mi[EE];
}
int solve(int nn){
        int v=0;
        REP(i,nn)v+=flow();
        return v;
}
int main(){
    int n,m,k;
    R(n,m,k,C,d);
    flow_clear(n*100+1);
    FOR(i,1,k){
        int x;
        R(x);
        add_edge(0,x,1,0,0);
    }
    FOR(i,1,99){
        add_edge(1+i*n,100*n+1,INF,0,0);
    }
    FOR(i,1,n){
        FOR(j,1,99){
            add_edge(i+(j-1)*n,i+j*n,INF,C,0);
        }
    }
    FOR(i,1,m){
        int x,y; R(x,y);
        FOR(j,1,99){
            add_edge(x+(j-1)*n,y+j*n,INF,C+d,1);
            add_edge(y+(j-1)*n,x+j*n,INF,C+d,1);
        }
    }
    W(solve(k));
    return 0;
}


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

#define vec vector
#define pb push_back
#define FOR(i, a, b) for(int i = (a); i < (b); i++)
#define FORE(i, a, b) for(int i = (a); i <= (b); i++)
#define FORD(i, a, b) for(int i = (a); i >= (b); i--)
const long long INF64 = 1e18;
typedef long long ll;

struct Edge {
  int from;
  int to;
  int f;
  int cost;

  Edge() {};

  Edge(int _from, int _to, int _f, int _cost)
    : from(_from), to(_to), f(_f), cost(_cost) {};
};

vec<Edge> e;

const int N = 1e6 + 7;
vec<int> g[N];

ll ans = 0;
ll dist[N];
int pred[N];
int pe[N];
int inq[N];

int source = N - 2;
int target = N - 1;

int residualCapacity(int x) {
  return e[x].to - e[x].f;
}

void dijkstra() {
  FOR(i, 0, N) {
    dist[i] = INF64;
    pred[i] = -1;
    pe[i] = -1;
    inq[i] = 0;
  }
  dist[source] = 0;
  queue<int> q;
  q.push(source);
  inq[source] = 1;
  while (!q.empty()) {
    int k = q.front(); q.pop();
    inq[k] = 0;
    for (auto x : g[k]) {
      if (!residualCapacity(x)) {
        continue;
      }
      int cost = e[x].cost;
      int y = e[x].from;
      if (dist[y] > dist[k] + cost) {
        dist[y] = dist[k] + cost;
        pred[y] = k;
        pe[y] = x;
        if (inq[y] == 0) {
          inq[y] = 1;
          q.push(y);
        }
      }
    }
  }
}

void pushFlow() {
  dijkstra();
  int cur = target;
  //vec<int> zz(1, cur);
  while (cur != source) {
    e[pe[cur]].f++;
    e[pe[cur] ^ 1].f--;
    cur = pred[cur];
    //zz.push_back(cur);
  }
  //reverse(zz.begin(), zz.end());
  //for (auto x : zz) {cerr << x << " ";}
  //cerr << "\n";
  ans += dist[target];
}

void addEdge(int x, int y, int capacity, int cost) {
  g[x].push_back(e.size());
  e.push_back(Edge(y, capacity, 0, cost));
  g[y].push_back(e.size());
  e.push_back(Edge(x, 0, 0, -cost));
}

int n, m, k, c, d;
int timeLayers = 101;

void inputAndBuildGraph() {
  //freopen("??.in", "r", stdin);
  //freopen("??.out", "w", stdout);
  scanf("%d %d %d %d %d", &n, &m, &k, &c, &d);
  FOR(i, 0, k) {
    int x;
    scanf("%d", &x);
    --x;
    addEdge(source, x, 1, 0);
  }
  FOR(i, 0, timeLayers) {
    addEdge(i * n, target, k, i * c);
  }
  FOR(i, 0, m) {
    int x, y;
    scanf("%d %d", &x, &y);
    --x, --y;
    FOR(i, 0, timeLayers - 1) FOR(j, 0, k) {
      addEdge(x + i * n, y + i * n + n, 1, d * (j * 2 + 1));
    }
    FOR(i, 0, timeLayers - 1) FOR(j, 0, k) {
      addEdge(y + i * n, x + i * n + n, 1, d * (j * 2 + 1));
    }
  }
}

void solve() {
  FOR(i, 0, n) FOR(j, 0, timeLayers - 1) {
    addEdge(i + j * n, i + j * n + n, k, 0);
  }
  FOR(i, 0, k) {
    pushFlow();
  }
  printf("%lld\n", ans);

  // read the question correctly (is y a vowel?)
  // look out for SPECIAL CASES (n=1?) and overflow (ll vs int?)
}

int main() {
  //auto beginProgram = chrono::steady_clock::now();
  {
    inputAndBuildGraph();
    solve();
  }
  //auto endProgram = chrono::steady_clock::now();

  return 0;
}


#include<bits/stdc++.h>

using namespace std;

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

vector<edge> e;

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

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

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

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

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

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

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

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


#include<bits/stdc++.h>
#define long long long
using namespace std;
const int N=1e6;
int fr[N+2],sr,sn;
vector<int>gr[N+2];

const int inf=1e9;
struct edge
{
  int a,b,f,c,d;
};
vector<edge>ed;
vector<int>adj[N+2];
void addEdge(int a,int b,int c,int d)
{
  edge e;e={a,b,0,c,d};
  adj[a].push_back(ed.size());
  ed.push_back(e);

  e={b,a,0,0,-d};
  adj[b].push_back(ed.size());
  ed.push_back(e);
}
int dis[N+2],inq[N+2],mnf[N+2],pth[N+2];
pair<int,int>spfa(int n)
{
  for(int i=0;i<=n;i++)dis[i]=inf;
  queue<int>q;q.push(sr);
  dis[sr]=0,inq[sr]=1,mnf[sr]=inf;
  while(!q.empty())
  {
    int u=q.front();q.pop();inq[u]=0;
    for(auto id:adj[u])
    {
      int v=ed[id].b;
      if(ed[id].c>ed[id].f&&dis[v]>dis[u]+ed[id].d)
      {
        dis[v]=dis[u]+ed[id].d,pth[v]=id;
        mnf[v]=min(mnf[u],ed[id].c-ed[id].f);
        if(!inq[v])q.push(v),inq[v]=1;
      }
    }
  }
  if(dis[sn]==inf)return {0,0};
  int v=sn;
  while(v!=sr)
  {
    int id=pth[v];
    ed[id].f+=mnf[sn],ed[id^1].f-=mnf[sn];
    v=ed[id].a;
  }
  return {mnf[sn],dis[sn]*mnf[sn]};
}
pair<int,int>mcmf(int n)
{
  int flow=0,cost=0;
  while(true)
  {
    pair<int,int>p=spfa(n);
    if(!p.first)return {flow,cost};
    flow+=p.first,cost+=p.second;
  }
}

int main()
{
  ios_base::sync_with_stdio(0);cin.tie(0);
  int n,m,k,c,d;cin>>n>>m>>k>>c>>d;
  for(int i=1;i<=k;i++)
  {
    int x;cin>>x;fr[x]++;
  }
  for(int i=1;i<=m;i++)
  {
    int u,v;cin>>u>>v;
    gr[u].push_back(v);
    gr[v].push_back(u);
  }
  sr=0,sn=100*n+n+1;
  for(int tm=0;tm<=99;tm++)
  {
    for(int i=1;i<=n;i++)
    {
      addEdge(n*tm+i,n*(tm+1)+i,k,0);
      for(auto x:gr[i])
      {
        for(int cp=1;cp<=k;cp++)
        {
          addEdge(n*tm+i,n*(tm+1)+x,1,d*(2*cp-1));
        }
      }
    }
  }
  for(int i=1;i<=n;i++)
    if(fr[i])addEdge(sr,i,fr[i],0);
  for(int tm=0;tm<=100;tm++)
    addEdge(n*tm+1,sn,k,c*tm);
  cout<<mcmf(sn).second<<endl;
  return 0;
}


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

const int maxn = 6010, INF = 0x3f3f3f3f;
int n, m, k, c, d, cnt, ans, a[maxn], x[maxn], y[maxn];
int head[maxn], pre[maxn], dist[maxn], inq[maxn];
queue<int> q;
struct edge { int to, cap, cost, nxt; } e[2000010];
int id(int t, int v) { return t * n + v; }

void add(int from, int to, int cap, int cost) {
    e[cnt] = (edge){to, cap, cost, head[from]}, head[from] = cnt++;
    e[cnt] = (edge){from, 0, -cost, head[to]}, head[to] = cnt++;
}

bool spfa(int s, int t) {
    memset(dist, 0x3f, sizeof(dist));
    q.push(s), dist[s] = 0;
    while (!q.empty()) {
        int v = q.front(); q.pop(), inq[v] = 0;
        for (int i = head[v], u; ~i; i = e[i].nxt) {
            if (e[i].cap && dist[u = e[i].to] > dist[v] + e[i].cost) {
                dist[u] = dist[v] + e[i].cost, pre[u] = i;
                if (!inq[u]) q.push(u), inq[u] = 1;
            }
        }
    }
    return dist[t] < 1e9;
}

void upd(int s, int t) {
    for (int i = t; i ^ s; i = e[pre[i] ^ 1].to) {
        e[pre[i]].cap--, e[pre[i] ^ 1].cap++;
    }
    ans += dist[t];
}

int main() {
    memset(head, -1, sizeof(head));
    scanf("%d %d %d %d %d", &n, &m, &k, &c, &d);
    int S = 0, T = 6000;
    for (int i = 1; i <= k; i++) {
        scanf("%d", &a[i]), add(S, id(0, a[i]), 1, 0);
    }
    for (int i = 1; i <= m; i++) {
        scanf("%d %d", &x[i], &y[i]);
    }
    for (int t = 0; t <= 100; t++) {
        for (int i = 2; i <= n; i++) {
            add(id(t, i), id(t + 1, i), k, c);
        }
        add(id(t, 1), T, k, 0);
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= min(k, 25); j++) {
                add(id(t, x[i]), id(t + 1, y[i]), 1, c + (2 * j - 1) * d);
                add(id(t, y[i]), id(t + 1, x[i]), 1, c + (2 * j - 1) * d);
            }
        }
    }
    while (spfa(S, T)) upd(S, T);
    printf("%d\n", ans);
    return 0;
}


#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<deque>
#include<stack>
#include<string>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<bitset>
#include<stdlib.h>
#include<cassert>
#include<time.h>
#include<bitset>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
const long long d2=(mod+1)/2;
const long double EPS=1e-9;
const long double PI=acos(-1.0);
int ABS(int a){return max(a,-a);}
long long ABS(long long a){return max(a,-a);}
long double ABS(long double a){return max(a,-a);}

namespace MCF {
	// required <string.h> <vector> <queue> <algorithm>
	#define MAXN 15400
	#define MAXM 3100000
	#define wint int
	#define cint long long
	const wint wEPS = 0;
	const wint wINF = 1001001001;
	const cint cEPS = 0;
	const cint cINF = 100100100100100100LL;
	int n, m, ptr[MAXN], next[MAXM], zu[MAXM];
	wint capa[MAXM], tof;
	cint cost[MAXM], toc, d[MAXN], pot[MAXN];
	int vis[MAXN], pree[MAXN];
	void init(int _n) {
		n = _n; m = 0; memset(ptr, ~0, n * 4);
	}
	void ae(int u, int v, wint w, cint c) {
		next[m] = ptr[u]; ptr[u] = m; zu[m] = v; capa[m] = w; cost[m] = +c; ++m;
		next[m] = ptr[v]; ptr[v] = m; zu[m] = u; capa[m] = 0; cost[m] = -c; ++m;
	}
	bool solve(int src, int ink, wint flo = wINF) {
		int i, u, v;
		wint f;
		cint c, cc;
		memset(pot, 0, n * sizeof(cint));
		//*
		for (bool cont = 1; cont; ) {
			cont = 0;
			for (u = 0; u < n; ++u) for (i = ptr[u]; ~i; i = next[i]) if (capa[i] > wEPS) {
				if (pot[zu[i]] > pot[u] + cost[i] + cEPS) {
					pot[zu[i]] = pot[u] + cost[i]; cont = 1;
				}
			}
		}
		//*/
		for (toc = 0, tof = 0; tof + wEPS < flo; ) {
			typedef pair<cint,int> node;
			priority_queue< node,vector<node>,greater<node> > q;
			for (u = 0; u < n; ++u) { d[u] = cINF; vis[u] = 0; }
			for (q.push(make_pair(d[src] = 0, src)); !q.empty(); ) {
				c = q.top().first; u = q.top().second; q.pop();
				if (vis[u]++) continue;
				for (i = ptr[u]; ~i; i = next[i]) if (capa[i] > wEPS) {
					cc = c + cost[i] + pot[u] - pot[v = zu[i]];
					if (d[v] > cc + cEPS) { q.push(make_pair(d[v] = cc, v)); pree[v] = i; }
				}
			}
			if (!vis[ink]) return 0;
			f = flo - tof;
			for (v = ink; v != src; v = zu[i ^ 1]) { i = pree[v]; f=min(f,capa[i]); }
			for (v = ink; v != src; v = zu[i ^ 1]) { i = pree[v]; capa[i] -= f; capa[i ^ 1] += f; }
			tof += f;
			toc += f * (d[ink] - pot[src] + pot[ink]);
			for (u = 0; u < n; ++u) pot[u] += d[u];
		}
		return 1;
	}
}
int big[60];
int x[60];
int y[60];
int main(){
	int a,b,c,d,e;
	scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
	for(int i=0;i<c;i++){
		int p;scanf("%d",&p);p--;
		big[p]++;
	}
	for(int i=0;i<b;i++){
		scanf("%d%d",x+i,y+i);x[i]--;y[i]--;
	}
	MCF::init(a*103+2);
	int S=a*103;
	int T=a*103+1;
	for(int i=0;i<103;i++){
		MCF::ae(i*a,T,50,i*d);
		if(i<102){
			for(int j=0;j<b;j++){
				for(int k=0;k<c;k++){
					MCF::ae(i*a+x[j],i*a+y[j]+a,1,e*(k*2+1));
					MCF::ae(i*a+y[j],i*a+x[j]+a,1,e*(k*2+1));
				}
			}
			for(int j=0;j<a;j++){
				MCF::ae(i*a+j,i*a+j+a,50,0);
			}
		}
	}
	for(int i=0;i<a;i++){
		MCF::ae(S,i,big[i],0);
	}
	MCF::solve(S,T,c);
	printf("%lld\n",MCF::toc);
}


#include <bits/stdc++.h>
using namespace std;
const int INF = 0x7f7f7f7f;
int n,m,s,t,p,c,d,x[505],y[505];
int mxf,mnc;
int ee=1,h[5000005],nex[5000005<<1],to[5000005<<1],val[5000005<<1],cost[5000005<<1];
int dis[5000005],pre[5000005],last[5000005],flow[5000005];
bool vis[5000005];
void addedge(int x,int y,int z,int c)
{
	nex[++ee] = h[x];
	to[ee] = y;
	val[ee] = z;
	cost[ee] = c;
	h[x] = ee;
}
bool spfa()
{
	memset(dis,INF,sizeof(dis));
	memset(vis,false,sizeof(vis));
	queue<int> q;
	q.push(s);
	vis[s] = true;
	dis[s] = 0;
	flow[s] = INF;
	pre[t] = -1;
	while(!q.empty())
	{
		int x=q.front();
		q.pop();
		vis[x] = false;
		for(int i=h[x];i;i=nex[i])
			if(val[i] && dis[to[i]]>dis[x]+cost[i])
			{
				dis[to[i]] = dis[x]+cost[i];
				pre[to[i]] = x;
				last[to[i]] = i;
				flow[to[i]] = min(flow[x],val[i]);
				if(!vis[to[i]])
				{
					vis[to[i]] = true;
					q.push(to[i]);
				}
			}
	}
	return pre[t]!=-1;
}
void mcmf()
{
	mxf = mnc = 0;
	while(spfa())
	{
		int now=t;
		mxf += flow[t];
		mnc += flow[t]*dis[t];
		while(now!=s)
		{
			val[last[now]] -= flow[t];
			val[last[now]^1] += flow[t];
			now = pre[now];
		}
	}
}
int zh(int t,int x)
{
	return t*n+x;
}
int main()
{
	cin>>n>>m>>p>>c>>d;
	s = 0, t = n*99+1;
	for(int i=1,x;i<=p&&cin>>x;i++)
		addedge(s,zh(0,x),1,0), addedge(zh(0,x),s,0,0);
	for(int i=1;i<=m;cin>>x[i]>>y[i],i++);
	for(int i=0;i<=99;i++)
	{
		addedge(zh(i,1),zh(i+1,1),INF,0), addedge(zh(i+1,1),zh(i,1),0,0);
		for(int j=2;j<=n;j++)
			addedge(zh(i,j),zh(i+1,j),INF,c), addedge(zh(i+1,j),zh(i,j),0,-c);
		for(int j=1;j<=m;j++)
			for(int k=1;k<=p;k++)
			{
				int cst=d*k*k-d*(k-1)*(k-1)+c;
				addedge(zh(i,x[j]),zh(i+1,y[j]),1,cst), addedge(zh(i+1,y[j]),zh(i,x[j]),0,-cst);
				addedge(zh(i,y[j]),zh(i+1,x[j]),1,cst), addedge(zh(i+1,x[j]),zh(i,y[j]),0,-cst);
			}
	}
	mcmf();
	cout<<mnc<<endl;
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define frr(frm,fornn)for(int i=frm; i<fornn; i++)
#define rfrr(frm,fornn)for(int i=frm; i>=fornn; i--)
#define fr(iii,frm,fornn)for(int iii=frm; iii<fornn; iii++)
#define rfr(iii,frm,fornn)for(int iii=frm; iii>=fornn; iii--)
#define itfr(iii,frm)for(auto iii=frm.begin(); iii!=frm.end(); iii++)
#define ll long long int
#define lll unsigned long long int
#define pb push_back
#define seet(seta) memset(seta,-1,sizeof(seta))
#define clr(seta) memset(seta,0,sizeof(seta))
#define clr2(seta,xxxx,yyyy) memset(seta,0,sizeof(int)*xxxx*yyyy)
#define seet2(seta,xxxx,yyyy) memset(seta,-1,sizeof(int)*xxxx*yyyy)
#define E "\n"
#define infi 10000000000000
#define F first
#define S second
typedef vector <int> ve;
typedef vector <bool> vb;

#define mx (int) 1000000007

void solve()
{
	lll n;
	cin>>n;
	lll sum=1;
	frr(1,n+1)
	{
		sum%=mx;
		sum*=i;
	}
	lll x=1;
	frr(1,n)
	{
		x%=mx;
		x*=2;
	}
	cout<<(sum-x)%mx<<E;
}

int main()
{
	//freopen("input.txt","r",stdin);
	//freopen("output.txt","w",stdout);
	int tc,cse=0;
	//cin>>tc;
	//while(tc--)
		solve();
}


#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <math.h>
#include <vector>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <string>
#include <cstring>
#include <time.h>
#include <map>

using namespace std;

typedef long long ll;

ll n, m;
deque <ll> d;
ll A[1000];
vector <ll> v;

int main() {
	string s;
	cin >> n;
	cin >> s;
	for (ll i = 1; i <= n; i++) {
		if (s.length() % i == 0) {
			v.push_back(i);
		}
	}
	for (ll i = 0; i < v.size(); i++) {
		string d = "";
		for (ll j = 0; j < v[i]; j++) {
			d.push_back(s[j]);
		}
		reverse(d.begin(), d.end());
		for (ll j = v[i]; j < n; j++) {
			d.push_back(s[j]);
		}
		s = d;
	}
	cout << s;
	return 0;
}


#include <algorithm>
#include <iostream>
#include <bits/stdc++.h>
#include<iomanip>
#include<string>
#include <deque>
#include <queue>
//#include <ext/pb_ds/assoc_container.hpp> // Common file
//#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update
//using namespace __gnu_pbds;

using namespace std;
const int64_t mod = 1e9 + 7;
const int64_t Mod = 998244353;
//typedef tree<int64_t,null_type,less<int64_t>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;

int64_t GCD(int64_t m ,int64_t n)
{
    int64_t temp1 =max(m,n);
    int64_t temp2 =min(m,n);
    m=temp1;
    n=temp2;
    if(m%n==0)
    {
        return n;
    }
    else
    {
        return GCD(m%n,n);
    }
}

int64_t divisors (int64_t n,vector<int64_t> &V)
{
    int64_t ans=1;
    while(n%2==0)
    {
        n=n/2;
          V.push_back(2);
        ans++;
    }
    for(int64_t i=3;i*i<=n;i+=2)
    { int64_t cnt =1;
        while(n%i==0)
        {
            n=n/i;
            V.push_back(i);

            cnt++;
        }
        ans *=cnt;
    }
    if(n>1)
    {
        V.push_back(n);
        ans *=2;
    }

    return ans;
}

int number(int64_t l)
{
    int cnt=0;
    while(l>0)
    {
        cnt++;
        l/=2;
    }
    return cnt;
}

int64_t calpow(int64_t B, int64_t pow, int64_t mod)
{
  int64_t mul = 1;
  while (pow > 0)
  {
    if (pow & 1)
    {
      mul = ((B % mod) * (mul % mod)) % mod;
      pow--;
    }
    else
    {
      B = ((B % mod) * (B % mod)) % mod;
      pow /= 2;
    }
  }
  return mul;
}

// ** Few Imp Tips/Facts ** //
/* (a+b) =  (a&b) + (a|b) IMP*/
//MAPS TAKE A LOT OF TIME,REMEMBER//
//Hockey Stick Identity: sigma(icr) = n+1cr+1;//

vector<int64_t > fac(200007,0);

int64_t modInverse(int64_t n,int64_t p)
{
    return calpow(n, p - 2, p);
}

int64_t nCrModPFermat(int64_t n,int64_t r, int64_t p)
{

    if (n < r)
        return 0;

    if (r == 0)
        return 1;

    return (fac[n] * modInverse(fac[r], p) % p
            * modInverse(fac[n - r], p) % p)
           % p;
}

/*Let g = gcd(a, b)g=gcd(a,b). While g ! =1, divide aa by gg and repeat. If at the end, aa equals 11, then bb is divisible by each prime factor of aa, and not otherwise.*/
/*Good method to find each prime factor*/
int64_t _mergeSort(int64_t arr[], int64_t temp[], int64_t left, int64_t right);
int64_t merge(int64_t arr[], int64_t temp[], int64_t left, int64_t mid,int64_t right);

/* This function sorts the
   input array and returns the
number of inversions in the array */
int64_t mergeSort(int64_t arr[], int64_t array_size)
{
    int64_t temp[array_size];
    return _mergeSort(arr, temp, 0, array_size - 1);
}

/* An auxiliary recursive function
  that sorts the input array and
returns the number of inversions in the array. */
int64_t _mergeSort(int64_t arr[], int64_t temp[], int64_t left, int64_t right)
{
    int64_t  mid, inv_count = 0;
    if (right > left) {
        /* Divide the array into two parts and
        call _mergeSortAndCountInv()
        for each of the parts */
        mid = (right + left) / 2;

        /* Inversion count will be sum of
        inversions in left-part, right-part
        and number of inversions in merging */
        inv_count += _mergeSort(arr, temp, left, mid);
        inv_count += _mergeSort(arr, temp, mid + 1, right);

        /*Merge the two parts*/
        inv_count += merge(arr, temp, left, mid + 1, right);
    }
    return inv_count;
}

/* This funt merges two sorted arrays
and returns inversion count in the arrays.*/
int64_t merge(int64_t arr[], int64_t temp[], int64_t left, int64_t mid,int64_t right)
{
    int64_t i, j, k;
    int64_t inv_count = 0;

    i = left; /* i is index for left subarray*/
    j = mid; /* j is index for right subarray*/
    k = left; /* k is index for resultant merged subarray*/
    while ((i <= (mid - 1)) && (j <= right)) {
        if (arr[i] <= arr[j]) {
            temp[k++] = arr[i++];
        }
        else {
            temp[k++] = arr[j++];

            /* this is tricky -- see above
            explanation/diagram for merge()*/
            inv_count = inv_count + (mid - i);
        }
    }

    /* Copy the remaining elements of left subarray
(if there are any) to temp*/
    while (i <= (mid - 1))
       {

        temp[k++] = arr[i++];
       }

    /* Copy the remaining elements of right subarray
       (if there are any) to temp*/
    while (j <= right)
        {temp[k++] = arr[j++];}

    /*Copy back the merged elements to original array*/
    for (i = left; i <= right; i++)
        {arr[i] = temp[i];}

    return inv_count;
}
bool compare(string a,string b)
{
    for(int i=0;i<a.size();i++)
    {
        if(a[i]!=b[i])
        {
            if((i%2))
            {
                if(a[i]>b[i])
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                if(a[i]>b[i])
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
        }
    }
}
void MAXHEAPIFY(int64_t *A,vector< string> V,int64_t i,int64_t n) //If at any node there is a parent node whose child's value is greater thanit ,then this will modiify the heap accordingly.
{
    int64_t MAX =i;
    int64_t l = (2*i); //Left child.
    int64_t r = (2*i)+1; //Right child.

    if((l<=n) && (compare(V[A[l]-1],V[A[MAX]-1])))
    {
        MAX =l;
    }
    if((r<=n) && (compare(V[A[r]-1],V[A[MAX]-1])))
    {
        MAX =r;
    }
    if(MAX!=i)
    {

        swap(A[i],A[MAX]); // Exchange child with parent.

        MAXHEAPIFY(A,V,MAX,n);// Check for cases of violation at new positon.
    }
    else
    {return;}
}
void BuidHeap(int64_t *A,vector< string> V,int64_t n) // Buids a heap structure out of any array.
{
       for(int64_t i = (n/2);i>=1;i--)
       {
           MAXHEAPIFY(A,V,i,n);

       }
}
void HeapSort(int64_t *A,vector< string> V,int64_t n)//sorts the array using heap structure.
{
    BuidHeap(A,V,n);

    for(int64_t i =n;i>=2;i--)
    {
        swap(A[1],A[i]);
        MAXHEAPIFY(A,V,1,i-1);
    }
}
bool check(char a)
{
    if(a == '_')
    {
        return false;
    }

    return true;
}
       /*K fibonnaic numbers implementation done using sum*/
int64_t solve(string s)
{
    int64_t ans =1;
    int64_t y =1;
    int n = s.size();
     if(n==1)
     {
         if((s[0]=='0')||(s[0]=='_'))
         {
             return 1;
         }
         else
         {
             return 0;
         }
     }

     else if(s[0] == '0')
     {
         return 0;
     }

    if((check(s[n-1]))&&(check(s[n-2])))
    {    int f = (int)(s[n-2]-'0');
    f *=10;
    int x  = (int)(s[n-1]-'0');
    f +=x;

        if((f%25)!=0)
        {
            return 0;
        }

        y =1;
    }
    else if((check(s[n-1]))&&(!check(s[n-2])))
    {
        if((s[n-1]=='0')||(s[n-1]=='5'))
           {
               y = 2;
           }
           else
            {
                return 0;
            }
    }
    else if((check(s[n-2]))&&(!check(s[n-1])))
    {
        if((s[n-2]=='0')||(s[n-2]=='2')||(s[n-2]=='5')||(s[n-2]=='7'))
           {
               y =1;
           }
           else
            {
                return 0;
            }
    }
    else if((!check(s[n-2]))&&(!check(s[n-1])))
    {
        y =4;
    }

    for(int i=n-3;i>=0;i--)
    {
        if(s[i]=='_')
        {    if(i!=0)
            {ans *=10;}
            else
            {
                ans *=9;
            }
        }
    }

    if(y==4)
    {
        if(n==2)
        {
            ans *=3;
        }
        else
        {
            ans *=4;
        }
    }
    if(y==2)
    {
       if(n==2)
       {if(s[1]=='0')
        {
            ans =ans;
        }
        else
        {
            ans = 2*ans;
        }
       }
       else
       {
           ans = 2*ans;
       }
    }
    if(y==1)
    {
        ans = ans;
    }

    return ans;

}

int main()
{
    ios_base::sync_with_stdio(false);
     cin.tie(NULL);
      /*fac[0] = 1;
    for (int i = 1; i <= 200006; i++)
       {

        fac[i] = (fac[i - 1] * i) % Mod;
       }*/

           string s;
        cin>>s;

        int n =s.size();
        int64_t ans =0;
        bool xpresent = false;
        for(int i=0;i<n;i++)
        {
            if(s[i]=='X')
            {
                xpresent =true;
                break;
            }
        }
        if(xpresent)
        {
             for(int i=0;i<10;i++)
             {  string h = s;
             char e = (char)(i+'0');
                 for(int j =0;j<n;j++)
                 {
                     if(h[j]=='X')
                     {
                         h[j] = e;
                     }
                 }
                  //cout<<h<<": "<<solve(h)<<endl;
                 ans += solve(h);
             }
             cout<<ans<<endl;
        }
        else
        {

            cout<<solve(s)<<endl;
        }

}