import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.util.Arrays;
import java.util.Scanner;

public class CF_2020_GlobalRound_E {
	static boolean verb=true;
	static void log(Object X){if (verb) System.err.println(X);}
	static void log(Object[] X){if (verb) {for (Object U:X) System.err.print(U+" ");System.err.println("");}}
	static void log(int[] X){if (verb) {for (int U:X) System.err.print(U+" ");System.err.println("");}}
	static void log(int[] X,int L){if (verb) {for (int i=0;i<L;i++) System.err.print(X[i]+" ");System.err.println("");}}
	static void log(long[] X){if (verb) {for (long U:X) System.err.print(U+" ");System.err.println("");}}

	static InputReader reader;

	static long[][] binom;

	static void buildBinom(int N){
		int MAX=N+1;
		binom=new long[MAX+1][];
		for (int i=0;i<MAX+1;i++)
			binom[i]=new long[i+1];
		binom[0][0]=1;
		for (int i=1;i<MAX;i++){
			binom[i][0]=1;
			binom[i][i]=1;
			for (int j=0;j<i;j++) {
				binom[i+1][j+1]=(binom[i][j]+binom[i][j+1])%mod;
			}
			//log(binom[i]);
		}
		log("binom done");
	}
	static long mod;

	static long solve(int n) {
		long[] pow2=new long[n+1];
		pow2[0]=1;
		for (int i=1;i<=n;i++) {
			pow2[i]=pow2[i-1]<<1;
			while (pow2[i]>=mod)
				pow2[i]-=mod;
		}
		buildBinom(n);

		long[][] dp=new long[n+1][n+1];
		dp[1][1]=1;
		for (int i=1;i<=n;i++) {
			dp[i][i]=pow2[i-1];
			//log("base:"+dp[i][i]);
			for (int j=1;j<i-1;j++){
				int me=i-j-1;
				for (int cn=1;cn<=j;cn++) {
					//log("j:"+j+" cn:"+cn+" dp:"+dp[j][cn]);
					//log("perm:"+binom[cn+me][cn]);
					dp[i][cn+me]+=(((dp[j][cn]*binom[cn+me][cn])%mod)*pow2[me-1])%mod;
					dp[i][cn+me]%=mod;
				}
			}
		}
		long ans=0;
		for (int i=0;i<=n;i++) {
			ans+=dp[n][i];
			ans%=mod;
		}
		return ans;
	}

	public static void main(String[] args) throws Exception  {

		log(400*400*400);
		reader=new InputReader(System.in);
		int n=reader.readInt();
		mod=reader.readInt();

		System.out.println(solve(n));

	}

	static final class InputReader {
		private final InputStream stream;
		private final byte[] buf = new byte[1024];
		private int curChar;
		private int numChars;

		public InputReader(InputStream stream) {
			this.stream = stream;
		}

		private int read() throws IOException {
			if (curChar >= numChars) {
				curChar = 0;
				numChars = stream.read(buf);
				if (numChars <= 0) {
					return -1;
				}
			}
			return buf[curChar++];
		}

		public final String readString() throws IOException {
			int c = read();
			while (isSpaceChar(c)) {
				c = read();
			}
			StringBuilder res=new StringBuilder();
			do {
				res.append((char)c);
				c = read();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public final int readInt() throws IOException {
			int c = read();
			boolean neg=false;
			while (isSpaceChar(c)) {
				c = read();
			}
			char d=(char)c;
			//log("d:"+d);
			if (d=='-') {
				neg=true;
				c = read();
			}
			int res = 0;
			do {
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			//log("res:"+res);
			if (neg)
				return -res;
			return res;

		}

		public final long readLong() throws IOException {
			int c = read();
			boolean neg=false;
			while (isSpaceChar(c)) {
				c = read();
			}
			char d=(char)c;
			//log("d:"+d);
			if (d=='-') {
				neg=true;
				c = read();
			}
			long res = 0;
			do {
				res *= 10;
				res += c - '0';
				c = read();
			} while (!isSpaceChar(c));
			//log("res:"+res);
			if (neg)
				return -res;
			return res;

		}

		private boolean isSpaceChar(int c) {
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}
	}
}


import java.io.*;
import java.math.*;
import java.security.*;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.*;
import java.util.regex.*;
import java.util.stream.*;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

public class Main{

    static long MOD = 1_000_000_007L;
    //static long MOD = 998_244_353L;
    //static long MOD = 1_000_000_033L;
    static long inv2 = (MOD + 1) / 2;

    static int[][] dir = new int[][]{{1, 0}, {0, 1}, {-1, 0}, {0, -1}};
    static long lMax = 0x3f3f3f3f3f3f3f3fL;
    static int iMax = 0x3f3f3f3f;
    static HashMap <Long, Long> memo = new HashMap();
    static MyScanner sc = new MyScanner();
    //static ArrayList <Integer> primes;

    static int nn = 300000;
    static long[] pow2;
    static long [] fac;
    static long [] pow;
    static long [] inv;
    static long [] facInv;
    static int[] base;
    static int[] numOfDiffDiv;
    static int[] numOfDiv;
    static ArrayList <Integer> primes;
    //static int[] primes;
    static int ptr = 0;
    static boolean[] isPrime;

    //-----------PrintWriter for faster output---------------------------------
    public static PrintWriter out;
    public static void main(String[] args) {
        out = new PrintWriter(new BufferedOutputStream(System.out));
        // Start writing your solution here. -------------------------------------

        /*fac = new long[nn + 1];
        fac[1] = 1;
        for(int i = 2; i <= nn; i++)
            fac[i] = fac[i - 1] * i % MOD;*/

        /*pow2 = new long[nn + 1];
        pow2[0] = 1L;
        for(int i = 1; i <= nn; i++)
            pow2[i] = pow2[i - 1] * 2L;*/

        /*inv = new long[nn + 1];
        inv[1] = 1;
        for (int i = 2; i <= nn; ++i)
            inv[i] = (MOD - MOD / i) * inv[(int)(MOD % i)] % MOD;*/

        /*facInv = new long[nn + 1];
        facInv[0] = facInv[1] = 1;
        for (int i = 2; i <= nn; ++i)
            facInv[i] = facInv[i - 1] * inv[i] % MOD;*/

        /*numOfDiffDiv = new int[nn + 1];
        for(int i = 2; i <= nn; i++)
            if(numOfDiffDiv[i] == 0)
                for(int j = i; j <= nn; j += i)
                    numOfDiv[j] ++;*/

        /*numOfDiv = new int[nn + 1];
        numOfDiv[1] = 1;
        for(int i = 2; i <= nn; i++) {
            for(int j = 2; j * j <= i; j++) {
                if(i % j == 0) {
                    numOfDiv[i] = numOfDiv[i / j] + 1;
                    break;
                }
            }
        }*/

        //primes = sieveOfEratosthenes(100001);

        /*
        int t = 1;
        //t = sc.ni();
        while(t-- > 0) {
            //boolean res = solve();
            //out.println(res ? "YES" : "NO");
            long res = solve();
            out.println(res);
        }*/

        int t = 1, tt = 0;
        //t = sc.ni();
        for(int i = 1; i <40000; i++) squares.add(i * i);
        while(tt++ < t) {
            boolean res = solve();
            //out.println("Case #" + tt + ": " + res);
            //out.println(res ? "YES" : "NO");
        }
        out.close();
    }
    static HashSet <Integer> squares = new HashSet();

    static boolean solve() {
        /*String s = sc.nextLine();
        char[] c = s.toCharArray();
        int n = c.length;*/
        //int n = sc.ni();
        //long[] a =  new long[n];
        //for(int i = 0; i < n; i++) a[i] = sc.nl();
        long res = 0;
        int n = sc.ni();
        long m = sc.nl();
        long[][][] dp = new long[2][n + 3][n + 3];
        long[][][] dp2 = new long[2][n + 3][n + 3];
        dp[0][2][1] = dp[1][2][2] = dp2[0][1][1] = 1L;
        for(int i = 3; i <= n; i++) {
            long[][] bef = dp[0];
            long[][] aft = dp[1];
            long[][] nbef = new long[n + 3][n + 3];
            long[][] naft = new long[n + 3][n + 3];
            for(int len = 1; len <= i; len++) {
                for(int ind = 1; ind <= len; ind++) {
                    nbef[len + 1][1] += bef[len][ind];
                    nbef[len + 1][ind + 1] -= bef[len][ind];
                    naft[len + 1][ind + 1] += bef[len][ind];
                    //naft[len + 1][len + 2] -= bef[len][ind];
                    naft[len + 1][ind + 1] += aft[len][ind];
                    //naft[len + 1][len + 2] -= aft[len][ind];
                    nbef[len + 1][1] += dp2[0][len][ind] + dp2[1][len][ind];
                    //nbef[len + 1][len + 2] -= dp2[0][len][ind] + dp2[1][len][ind];
                }
            }
            for(int len = 1; len <= i; len++) {
                for(int ind = 1; ind <= len; ind ++) {
                    nbef[len][ind] = (nbef[len][ind] + nbef[len][ind - 1] + 10000000L * m) % m;
                    naft[len][ind] = (naft[len][ind] + naft[len][ind - 1] + 10000000L * m) % m;
                }
            }
            dp2 = dp;
            dp = new long[][][]{nbef, naft};
        }
        for(long[] row: dp[0])
            for(long i : row)
                res += i;
        for(long[] row: dp[1])
            for(long i : row)
                res += i;
            out.println(res % m);
        return false;
    }

    // edges to adjacency list by uwi
    public static int[][] packU(int n, int[] from, int[] to) {
        return packU(n, from, to, from.length);
    }

    public static int[][] packU(int n, int[] from, int[] to, int sup) {
        int[][] g = new int[n][];
        int[] p = new int[n];
        for (int i = 0; i < sup; i++) p[from[i]]++;
        for (int i = 0; i < sup; i++) p[to[i]]++;
        for (int i = 0; i < n; i++) g[i] = new int[p[i]];
        for (int i = 0; i < sup; i++) {
            g[from[i]][--p[from[i]]] = to[i];
            g[to[i]][--p[to[i]]] = from[i];
        }
        return g;
    }

    // tree diameter by uwi
    public static int[] diameter(int[][] g) {
        int n = g.length;
        int f0 = -1, f1 = -1, d01 = -1;
        int[] q = new int[n];
        boolean[] ved = new boolean[n];
        {
            int qp = 0;
            q[qp++] = 0; ved[0] = true;
            for(int i = 0;i < qp;i++){
                int cur = q[i];
                for(int e : g[cur]){
                    if(!ved[e]){
                        ved[e] = true;
                        q[qp++] = e;
                        continue;
                    }
                }
            }
            f0 = q[n-1];
        }
        {
            int[] d = new int[n];
            int qp = 0;
            Arrays.fill(ved, false);
            q[qp++] = f0; ved[f0] = true;
            for(int i = 0;i < qp;i++){
                int cur = q[i];
                for(int e : g[cur]){
                    if(!ved[e]){
                        ved[e] = true;
                        q[qp++] = e;
                        d[e] = d[cur] + 1;
                        continue;
                    }
                }
            }
            f1 = q[n-1];
            d01 = d[f1];
        }
        return new int[]{d01, f0, f1};
    }

    public static long c(int n, int k) {
        return (fac[n] * facInv[k] % MOD) * facInv[n - k] % MOD;
    }

    // SegmentTree range min/max query by uwi
    public static class SegmentTreeRMQ {
        public int M, H, N;
        public int[] st;

        public SegmentTreeRMQ(int n)
        {
            N = n;
            M = Integer.highestOneBit(Math.max(N-1, 1))<<2;
            H = M>>>1;
            st = new int[M];
            Arrays.fill(st, 0, M, Integer.MAX_VALUE);
        }

        public SegmentTreeRMQ(int[] a)
        {
            N = a.length;
            M = Integer.highestOneBit(Math.max(N-1, 1))<<2;
            H = M>>>1;
            st = new int[M];
            for(int i = 0;i < N;i++){
                st[H+i] = a[i];
            }
            Arrays.fill(st, H+N, M, Integer.MAX_VALUE);
            for(int i = H-1;i >= 1;i--)propagate(i);
        }

        public void update(int pos, int x)
        {
            st[H+pos] = x;
            for(int i = (H+pos)>>>1;i >= 1;i >>>= 1)propagate(i);
        }

        private void propagate(int i)
        {
            st[i] = Math.min(st[2*i], st[2*i+1]);
        }

        public int minx(int l, int r){
            int min = Integer.MAX_VALUE;
            if(l >= r)return min;
            while(l != 0){
                int f = l&-l;
                if(l+f > r)break;
                int v = st[(H+l)/f];
                if(v < min)min = v;
                l += f;
            }

            while(l < r){
                int f = r&-r;
                int v = st[(H+r)/f-1];
                if(v < min)min = v;
                r -= f;
            }
            return min;
        }

        public int min(int l, int r){ return l >= r ? 0 : min(l, r, 0, H, 1);}

        private int min(int l, int r, int cl, int cr, int cur)
        {
            if(l <= cl && cr <= r){
                return st[cur];
            }else{
                int mid = cl+cr>>>1;
                int ret = Integer.MAX_VALUE;
                if(cl < r && l < mid){
                    ret = Math.min(ret, min(l, r, cl, mid, 2*cur));
                }
                if(mid < r && l < cr){
                    ret = Math.min(ret, min(l, r, mid, cr, 2*cur+1));
                }
                return ret;
            }
        }
    }

    public static char[] rev(char[] a){char[] b = new char[a.length];for(int i = 0;i < a.length;i++)b[a.length-1-i] = a[i];return b;}

    public static double dist(double a, double b){
        return Math.sqrt(a * a + b * b);
    }

    public static long inv(long a){
        return quickPOW(a, MOD - 2);
    }

    public class Interval {
        int start;
        int end;
        public Interval(int start, int end) {
            this.start = start;
            this.end = end;
        }
    }

    public static ArrayList<Integer> sieveOfEratosthenes(int n) {
        boolean prime[] = new boolean[n + 1];
        Arrays.fill(prime, true);
        for (int p = 2; p * p <= n; p++) {
            if (prime[p]) {
                for (int i = p * 2; i <= n; i += p) {
                    prime[i] = false;
                }
            }
        }
        ArrayList<Integer> primeNumbers = new ArrayList<>();
        for (int i = 2; i <= n; i++) {
            if (prime[i]) {
                primeNumbers.add(i);
            }
        }
        return primeNumbers;
    }

    public static int lowerBound(int[] a, int v){ return lowerBound(a, 0, a.length, v); }
    public static int lowerBound(int[] a, int l, int r, int v)
    {
        if(l > r || l < 0 || r > a.length)throw new IllegalArgumentException();
        int low = l-1, high = r;
        while(high-low > 1){
            int h = high+low>>>1;
            if(a[h] >= v){
                high = h;
            }else{
                low = h;
            }
        }
        return high;
    }
    public static int rlowerBound(int[] a, int v){ return lowerBound(a, 0, a.length, v); }
    public static int rlowerBound(int[] a, int l, int r, int v)
    {
        if(l > r || l < 0 || r > a.length)throw new IllegalArgumentException();
        int low = l-1, high = r;
        while(high-low > 1){
            int h = high+low>>>1;
            if(a[h] <= v){
                high = h;
            }else{
                low = h;
            }
        }
        return high;
    }
    public static long C(int n, int m)
    {
        if(m == 0 || m == n) return 1l;
        if(m > n || m < 0) return 0l;
        long res = fac[n] * quickPOW((fac[m] * fac[n - m]) % MOD, MOD - 2) % MOD;

        return res;
    }
    public static long quickPOW(long n, long m)
    {
        long ans = 1l;
        while(m > 0)
        {
            if(m % 2 == 1)
                ans = (ans * n) % MOD;
            n = (n * n) % MOD;
            m >>= 1;
        }
        return ans;
    }
    public static long quickPOW(long n, long m, long mod)
    {
        long ans = 1l;
        while(m > 0)
        {
            if(m % 2 == 1)
                ans = (ans * n) % mod;
            n = (n * n) % mod;
            m >>= 1;
        }
        return ans;
    }

    public static int gcd(int a, int b)
    {
        if(a % b == 0) return b;
        return gcd(b, a % b);
    }
    public static long gcd(long a, long b)
    {
        if(a % b == 0) return b;
        return gcd(b, a % b);
    }

    static class Randomized {
        public static void shuffle(int[] data) {
            shuffle(data, 0, data.length - 1);
        }

        public static void shuffle(int[] data, int from, int to) {
            to--;
            for (int i = from; i <= to; i++) {
                int s = nextInt(i, to);
                int tmp = data[i];
                data[i] = data[s];
                data[s] = tmp;
            }
        }

        public static void shuffle(long[] data) {
            shuffle(data, 0, data.length - 1);
        }

        public static void shuffle(long[] data, int from, int to) {
            to--;
            for (int i = from; i <= to; i++) {
                int s = nextInt(i, to);
                long tmp = data[i];
                data[i] = data[s];
                data[s] = tmp;
            }
        }

        public static int nextInt(int l, int r) {
            return RandomWrapper.INSTANCE.nextInt(l, r);
        }
    }

    static class RandomWrapper {
        private Random random;
        public static final RandomWrapper INSTANCE = new RandomWrapper(new Random());

        public RandomWrapper() {
            this(new Random());
        }

        public RandomWrapper(Random random) {
            this.random = random;
        }

        public int nextInt(int l, int r) {
            return random.nextInt(r - l + 1) + l;
        }

    }

    //-----------MyScanner class for faster input----------
    public static class MyScanner {
        BufferedReader br;
        StringTokenizer st;

        public MyScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }
        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }
        int ni() {
            return Integer.parseInt(next());
        }
        long nl() {
            return Long.parseLong(next());
        }
        double nd() {
            return Double.parseDouble(next());
        }
        String nextLine(){
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }
    }
    //--------------------------------------------------------
}


import java.io.*;
import java.util.*;

public class E {

	public static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	public static PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));

	public static void main(String[] args) throws IOException {
		readInput();
		out.close();
	}

	static long[][] dp;
	static int n;
	static long m;

	static long pow(long b, long e) {
		if (e== 0) return 1;
		long r= pow(b,e/2);
		r = r * r % m;
		if ((e&1)==1) return r *b%m;
		return r;
	}

	static long modinv(long a) {return pow(a,m-2);}

	static long solve(int len, int num) {
		if (len == -1 && num == -1) return 1;
		if (num < 0 || len <= 0) return 0;
		if (dp[len][num] == -1) {
			dp[len][num] = 0;
			for (int i = 0; i < len; i++) {
				if (i == 1) continue;
				long sol = pow[len-i-1]*solve(i-1,num-1)%m;
				sol = sol * faci[len-i]% m;
				dp[len][num] += sol;
				dp[len][num] %= m;
			}

		}
		return dp[len][num];
	}
	static long[] fac, faci, pow;

	public static void readInput() throws IOException {
		// br = new BufferedReader(new FileReader(".in"));
		// out = new PrintWriter(new FileWriter(".out"));
		StringTokenizer st = new StringTokenizer(br.readLine());
		n = Integer.parseInt(st.nextToken());
		m = Long.parseLong(st.nextToken());
		fac = new long[500];
		pow = new long[500];
		faci = new long[fac.length];
		fac[0] = pow[0] = 1;
		faci[0] = modinv(fac[0]);
		for (int i = 1; i < fac.length; i++) {
			fac[i] = fac[i-1]*i%m;
			faci[i] = modinv(fac[i]);
			pow[i] = pow[i-1] * 2 % m;
		}
		dp = new long[n+1][n+1];
		for (long[] a: dp) Arrays.fill(a, -1);
		// Number of ways to make a segment of length x is 2^(x-1)
		// DP: Given position I.
		long ans =0 ;
		for (int i = 0 ; i <= n/2+1; i++) {
			//System.out.println(i + ": " + solve(n,i) + " " + (n-i) + " " + (i));
			long sol = solve(n,i) * fac[n-i];
			sol %= m;
			ans += sol;
		}
		out.println(ans%m);
	}
}


// upsolve with rainboy
import java.io.*;
import java.util.*;

public class CF1187G extends PrintWriter {
	CF1187G() { super(System.out); }
	static class Scanner {
		Scanner(InputStream in) { this.in = in; } InputStream in;
		int k, l; byte[] bb = new byte[1 << 15];
		byte getc() {
			if (k >= l) {
				k = 0;
				try { l = in.read(bb); } catch (IOException e) { l = 0; }
				if (l <= 0) return -1;
			}
			return bb[k++];
		}
		int nextInt() {
			byte c = 0; while (c <= 32) c = getc();
			int a = 0;
			while (c > 32) { a = a * 10 + c - '0'; c = getc(); }
			return a;
		}
	}
	Scanner sc = new Scanner(System.in);
	public static void main(String[] $) {
		CF1187G o = new CF1187G(); o.main(); o.flush();
	}

	static final int INF = 0x3f3f3f3f;
	ArrayList[] aa_;
	int n_, m_;
	int[] pi, dd, bb;
	int[] uu, vv, uv, cost;
	int[] cc;
	void init() {
		aa_ = new ArrayList[n_];
		for (int u = 0; u < n_; u++)
			aa_[u] = new ArrayList<Integer>();
		pi = new int[n_];
		dd = new int[n_];
		bb = new int[n_];
		qq = new int[nq];
		iq = new boolean[n_];
		uu = new int[m_];
		vv = new int[m_];
		uv = new int[m_];
		cost = new int[m_];
		cc = new int[m_ * 2];
		m_ = 0;
	}
	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;
		aa_[u].add(h << 1 ^ 0);
		aa_[v].add(h << 1 ^ 1);
	}
	int[] qq;
	int nq = 1, head, cnt;
	boolean[] iq;
	void enqueue(int v) {
		if (iq[v])
			return;
		if (head + cnt == nq) {
			if (cnt * 2 <= nq)
				System.arraycopy(qq, head, qq, 0, cnt);
			else {
				int[] qq_ = new int[nq *= 2];
				System.arraycopy(qq, head, qq_, 0, cnt);
				qq = qq_;
			}
			head = 0;
		}
		qq[head + cnt++] = v; iq[v] = true;
	}
	int dequeue() {
		int u = qq[head++]; cnt--; iq[u] = false;
		return u;
	}
	boolean spfa(int s, int t) {
		Arrays.fill(pi, INF);
		pi[s] = 0;
		head = cnt = 0;
		enqueue(s);
		while (cnt > 0) {
			int u = dequeue();
			int d = dd[u] + 1;
			ArrayList<Integer> adj = aa_[u];
			for (int h_ : adj)
				if (cc[h_] > 0) {
					int h = h_ >> 1;
					int p = pi[u] + ((h_ & 1) == 0 ? cost[h] : -cost[h]);
					int v = u ^ uv[h];
					if (pi[v] > p || pi[v] == p && dd[v] > d) {
						pi[v] = p;
						dd[v] = d;
						bb[v] = h_;
						enqueue(v);
					}
				}
		}
		return pi[t] != INF;
	}
	void push(int s, int t) {
		int c = INF;
		for (int u = t, h_, h; u != s; u ^= uv[h]) {
			h = (h_ = bb[u]) >> 1;
			c = Math.min(c, cc[h_]);
		}
		for (int u = t, h_, h; u != s; u ^= uv[h]) {
			h = (h_ = bb[u]) >> 1;
			cc[h_] -= c; cc[h_ ^ 1] += c;
		}
	}
	void push1(int s, int t) {
		for (int u = t, h_, h; u != s; u ^= uv[h]) {
			h = (h_ = bb[u]) >> 1;
			cc[h_]--; cc[h_ ^ 1]++;
		}
	}
	int edmonds_karp(int s, int t) {
		while (spfa(s, t))
			push1(s, t);
		int c = 0;
		for (int h = 0; h < m_; h++)
			c += cost[h] * cc[h << 1 ^ 1];
		return c;
	}
	void main() {
		int n = sc.nextInt();
		int m = sc.nextInt();
		int k = sc.nextInt();
		int c = sc.nextInt();
		int d = sc.nextInt();
		int[] ii = new int[k];
		for (int h = 0; h < k; h++)
			ii[h] = sc.nextInt() - 1;
		ArrayList[] aa = new ArrayList[n];
		for (int i = 0; i < n; i++)
			aa[i] = new ArrayList<Integer>();
		for (int h = 0; h < m; h++) {
			int i = sc.nextInt() - 1;
			int j = sc.nextInt() - 1;
			aa[i].add(j);
			aa[j].add(i);
		}
		int t = n + k + 1;
		n_ = n * t + 1;
		m_ = k + (m * 2 * k + n) * (t - 1);
		init();
		for (int i = 0; i < n; i++) {
			ArrayList<Integer> adj = aa[i];
			for (int s = 0; s < t - 1; s++) {
				int u = i * t + s;
				for (int j : adj) {
					int v = j * t + s + 1;
					for (int x = 1; x <= k; x++)
						link(u, v, 1, c + (x * 2 - 1) * d);
				}
			}
		}
		for (int i = 0; i < n; i++)
			for (int s = 0; s < t - 1; s++) {
				int u = i * t + s, v = u + 1;
				link(u, v, k, i == 0 ? 0 : c);
			}
		for (int h = 0; h < k; h++)
			link(n_ - 1, ii[h] * t + 0, 1, 0);
		println(edmonds_karp(n_ - 1, 0 * t + t - 1));
	}
}


//package com.company;

import java.io.*;
import java.util.*;

public class Main {
    public static class Task {

        public class Maxflow {
            class Edge {
                int t, rev;
                long cap, f;
                public Edge(int t, int rev, long cap) {
                    this.t = t;
                    this.rev = rev;
                    this.cap = cap;
                }
            }
            public Maxflow(int n) {
                graph = new List[n];
                for (int i = 0; i < n; i++) {
                    graph[i] = new ArrayList<>();
                }
            }
            List<Edge>[] graph;
            void addEdge(int s, int t, long cap) {
                graph[s].add(new Edge(t, graph[t].size(), cap));
                graph[t].add(new Edge(s, graph[s].size() - 1, 0));
//                System.err.println(s + " " + t + " " + cap);
            }

            boolean dinicBFS(int src, int dest, int[] dist) {
                Arrays.fill(dist, -1);
                dist[src] = 0;
                int[] Q = new int[graph.length];
                int sizeQ = 0;
                Q[sizeQ++] = src;
                for (int i = 0; i < sizeQ; i++) {
                    int u = Q[i];
                    for (Edge e: graph[u]) {
                        if (dist[e.t] < 0 && e.f < e.cap) {
                            dist[e.t] = dist[u] + 1;
                            Q[sizeQ++] = e.t;
                        }
                    }
                }
                return dist[dest] >= 0;
            }

            long dinicDFS(int[] ptr, int[] dist, int dest, int u, long f) {
                if (u == dest) return f;
                for (;ptr[u] < graph[u].size(); ++ptr[u]) {
                    Edge e =  graph[u].get(ptr[u]);
                    if (dist[e.t] == dist[u] + 1 && e.f < e.cap) {
                        long df = dinicDFS(ptr, dist, dest, e.t, Math.min(f, e.cap - e.f));
                        if (df > 0) {
                            e.f += df;
                            graph[e.t].get(e.rev).f -= df;
                            return df;
                        }
                    }
                }
                return 0;
            }

            long maxFLow(int src, int dest) {
                long flow = 0;
                int[] dist = new int[graph.length];
                while (dinicBFS(src, dest, dist)) {
                    int[] ptr = new int[graph.length];
                    while (true) {
                        long df = dinicDFS(ptr, dist, dest, src, Long.MAX_VALUE);
                        if (df == 0) break;
                        flow += df;
                    }
                }
                return flow;
            }
        }

        public class MinCostFlowBF {
            List<Edge>[] graph;
            class Edge {
                int to, f, cap, cost, rev;

                Edge(int v, int cap, int cost, int rev) {
                    this.to = v;
                    this.cap = cap;
                    this.cost = cost;
                    this.rev = rev;
                }
            }

            public MinCostFlowBF(int n) {
                graph = new List[n];
                for (int i = 0; i < n; i++)
                    graph[i] = new ArrayList<Edge>();
            }

            public void addEdge(int s, int t, int cap, int cost) {
                graph[s].add(new Edge(t, cap, cost, graph[t].size()));
                graph[t].add(new Edge(s, 0, -cost, graph[s].size() - 1));
            }

            void bellmanFord(int s, int[] dist, int[] prevnode, int[] prevedge, int[] curflow) {
                int n = graph.length;
                Arrays.fill(dist, 0, n, Integer.MAX_VALUE);
                dist[s] = 0;
                curflow[s] = Integer.MAX_VALUE;
                boolean[] inqueue = new boolean[n];
                int[] q = new int[n];
                int qt = 0;
                q[qt++] = s;
                for (int qh = 0; (qh - qt) % n != 0; qh++) {
                    int u = q[qh % n];
                    inqueue[u] = false;
                    for (int i = 0; i < graph[u].size(); i++) {
                        Edge e = graph[u].get(i);
                        if (e.f >= e.cap)
                            continue;
                        int v = e.to;
                        int ndist = dist[u] + e.cost;
                        if (dist[v] > ndist) {
                            dist[v] = ndist;
                            prevnode[v] = u;
                            prevedge[v] = i;
                            curflow[v] = Math.min(curflow[u], e.cap - e.f);
                            if (!inqueue[v]) {
                                inqueue[v] = true;
                                q[qt++ % n] = v;
                            }
                        }
                    }
                }
            }

            public int[] minCostFlow(int s, int t, int maxf) {
                int n = graph.length;
                int[] dist = new int[n];
                int[] curflow = new int[n];
                int[] prevedge = new int[n];
                int[] prevnode = new int[n];

                int flow = 0;
                int flowCost = 0;
                while (flow < maxf) {
                    bellmanFord(s, dist, prevnode, prevedge, curflow);
                    if (dist[t] == Integer.MAX_VALUE)
                        break;
                    int df = Math.min(curflow[t], maxf - flow);
                    flow += df;
                    for (int v = t; v != s; v = prevnode[v]) {
                        Edge e = graph[prevnode[v]].get(prevedge[v]);
                        e.f += df;
                        graph[v].get(e.rev).f -= df;
                        flowCost += df * e.cost;
                    }
                }
                return new int[]{flow, flowCost};
            }
        }

        public void solve(Scanner sc, PrintWriter pw) throws IOException {
            int n = sc.nextInt();
            int m = sc.nextInt();
            int k = sc.nextInt();
            int c = sc.nextInt();
            int d = sc.nextInt();
            int[] pos = new int[n];
            for (int i = 0; i < k; i++) {
                pos[sc.nextInt() - 1]++;
            }
            int T = 100;
            MinCostFlowBF mf = new MinCostFlowBF((T + 1) * n + 2);
            for (int i = 0; i < n; i++) {
                if (pos[i] > 0)
                    mf.addEdge(0, i + 1, pos[i], 0);
            }
            for (int i = 0; i < T; i++) {
                for (int j = 0; j < n; j++) {
                    mf.addEdge(1 + i * n + j, 1 + (i + 1) * n + j, k, 0);
                }
            }
            for (int i = 0; i <= T; i++) {
                for (int j = 1; j <= k; j++) {
                    mf.addEdge(1 + i * n, (T + 1) * n + 1, 1, c * i);
                }
            }
            for (int i = 0; i < m; i++) {
                int a = sc.nextInt() - 1;
                int b = sc.nextInt() - 1;
                for (int j = 0; j < T; j++) {
                    int cost = 0;
                    for (int l = 1; l <= k; l++) {
                        mf.addEdge(1 + j * n + a, 1 + (j + 1) * n + b, 1, l * l * d - cost);
                        mf.addEdge(1 + j * n + b, 1 + (j + 1) * n + a, 1, l * l * d - cost);
                        cost = l * l * d;
                    }
                }
            }
            int[] flowAndCost = mf.minCostFlow(0, (T + 1) * n + 1, k);
            System.err.println(flowAndCost[0]);
            pw.println(flowAndCost[1]);
        }
    }

    static long TIME_START, TIME_END;

    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
//        Scanner sc = new Scanner(new FileInputStream("input"));
        PrintWriter pw = new PrintWriter(new BufferedOutputStream(System.out));
//        PrintWriter pw = new PrintWriter(new FileOutputStream("output"));

        Runtime runtime = Runtime.getRuntime();
        long usedMemoryBefore = runtime.totalMemory() - runtime.freeMemory();
        TIME_START = System.currentTimeMillis();
        Task t = new Task();
        t.solve(sc, pw);
        TIME_END = System.currentTimeMillis();
        long usedMemoryAfter = runtime.totalMemory() - runtime.freeMemory();
        pw.close();
        System.err.println("Memory increased: " + (usedMemoryAfter - usedMemoryBefore) / 1000000);
        System.err.println("Time used: " + (TIME_END - TIME_START) + ".");
    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

        public Scanner(InputStream s) {
            br = new BufferedReader(new InputStreamReader(s));
        }

        public Scanner(FileReader s) throws FileNotFoundException {
            br = new BufferedReader(s);
        }

        public String next() throws IOException {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public int nextInt() throws IOException {
            return Integer.parseInt(next());
        }

        public long nextLong() throws IOException {
            return Long.parseLong(next());
        }

        public String nextLine() throws IOException {
            return br.readLine();
        }

        public double nextDouble() throws IOException {
            return Double.parseDouble(next());
        }

        public boolean ready() throws IOException {
            return br.ready();
        }
    }
}


// upsolve with rainboy
import java.io.*;
import java.util.*;

public class CF1187G extends PrintWriter {
	CF1187G() { super(System.out); }
	static class Scanner {
		Scanner(InputStream in) { this.in = in; } InputStream in;
		int k, l; byte[] bb = new byte[1 << 15];
		byte getc() {
			if (k >= l) {
				k = 0;
				try { l = in.read(bb); } catch (IOException e) { l = 0; }
				if (l <= 0) return -1;
			}
			return bb[k++];
		}
		int nextInt() {
			byte c = 0; while (c <= 32) c = getc();
			int a = 0;
			while (c > 32) { a = a * 10 + c - '0'; c = getc(); }
			return a;
		}
	}
	Scanner sc = new Scanner(System.in);
	public static void main(String[] $) {
		CF1187G o = new CF1187G(); o.main(); o.flush();
	}

	static final int INF = 0x3f3f3f3f;
	ArrayList[] aa_;
	int n_, m_;
	int[] pi, kk, bb;
	int[] uu, vv, uv, cost, cost_;
	int[] cc;
	void init() {
		aa_ = new ArrayList[n_];
		for (int u = 0; u < n_; u++)
			aa_[u] = new ArrayList<Integer>();
		pi = new int[n_];
		kk = new int[n_];
		bb = new int[n_];
		uu = new int[m_];
		vv = new int[m_];
		uv = new int[m_];
		cost = new int[m_];
		cost_ = new int[m_];
		cc = new int[m_ * 2];
		m_ = 0;
	}
	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;
		aa_[u].add(h << 1 ^ 0);
		aa_[v].add(h << 1 ^ 1);
	}
	void dijkstra(int s) {
		Arrays.fill(pi, INF);
		pi[s] = 0;
		TreeSet<Integer> pq = new TreeSet<>((u, v) -> pi[u] != pi[v] ? pi[u] - pi[v] : kk[u] != kk[v] ? kk[u] - kk[v] : u - v);
		pq.add(s);
		Integer first;
		while ((first = pq.pollFirst()) != null) {
			int u = first;
			int k = kk[u] + 1;
			ArrayList<Integer> adj = aa_[u];
			for (int h_ : adj)
				if (cc[h_] > 0) {
					int h = h_ >> 1;
					int p = pi[u] + ((h_ & 1) == 0 ? cost_[h] : -cost_[h]);
					int v = u ^ uv[h];
					if (pi[v] > p || pi[v] == p && kk[v] > k) {
						if (pi[v] < INF)
							pq.remove(v);
						pi[v] = p;
						kk[v] = k;
						bb[v] = h_;
						pq.add(v);
					}
				}
		}
	}
	void push(int s, int t) {
		int c = INF;
		for (int u = t, h_, h; u != s; u ^= uv[h]) {
			h = (h_ = bb[u]) >> 1;
			c = Math.min(c, cc[h_]);
		}
		for (int u = t, h_, h; u != s; u ^= uv[h]) {
			h = (h_ = bb[u]) >> 1;
			cc[h_] -= c; cc[h_ ^ 1] += c;
		}
	}
	void push1(int s, int t) {
		for (int u = t, h_, h; u != s; u ^= uv[h]) {
			h = (h_ = bb[u]) >> 1;
			cc[h_]--; cc[h_ ^ 1]++;
		}
	}
	int edmonds_karp(int s, int t) {
		System.arraycopy(cost, 0, cost_, 0, m_);
		while (true) {
			dijkstra(s);
			if (pi[t] == INF)
				break;
			push(s, t);
			for (int 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];
			}
		}
		int c = 0;
		for (int h = 0; h < m_; h++)
			c += cost[h] * cc[h << 1 ^ 1];
		return c;
	}
	void main() {
		int n = sc.nextInt();
		int m = sc.nextInt();
		int k = sc.nextInt();
		int c = sc.nextInt();
		int d = sc.nextInt();
		int[] ii = new int[k];
		for (int h = 0; h < k; h++)
			ii[h] = sc.nextInt() - 1;
		ArrayList[] aa = new ArrayList[n];
		for (int i = 0; i < n; i++)
			aa[i] = new ArrayList<Integer>();
		for (int h = 0; h < m; h++) {
			int i = sc.nextInt() - 1;
			int j = sc.nextInt() - 1;
			aa[i].add(j);
			aa[j].add(i);
		}
		int t = n + k + 1;
		n_ = n * t + 1;
		m_ = k + (m * 2 * k + n) * (t - 1);
		init();
		for (int i = 0; i < n; i++) {
			ArrayList<Integer> adj = aa[i];
			for (int s = 0; s < t - 1; s++) {
				int u = i * t + s;
				for (int j : adj) {
					int v = j * t + s + 1;
					for (int x = 1; x <= k; x++)
						link(u, v, 1, c + (x * 2 - 1) * d);
				}
			}
		}
		for (int i = 0; i < n; i++)
			for (int s = 0; s < t - 1; s++) {
				int u = i * t + s, v = u + 1;
				link(u, v, k, i == 0 ? 0 : c);
			}
		for (int h = 0; h < k; h++)
			link(n_ - 1, ii[h] * t + 0, 1, 0);
		println(edmonds_karp(n_ - 1, 0 * t + t - 1));
	}
}


import java.util.*;
import java.io.*;

public class GG {
    public static void main(String[] args) {
        FastScanner scanner = new FastScanner();
        PrintWriter out = new PrintWriter(System.out);
        int N = scanner.nextInt();
        int M = scanner.nextInt();
        int K = scanner.nextInt();
        int C = scanner.nextInt();
        int D = scanner.nextInt();
        MinCostMaxFlowSolver solver = new EdmondsKarp();
        int[] people = new int[K];
        for(int i = 0; i < K; i++) people[i] = scanner.nextInt()-1;
        Node src = solver.addNode();
        Node snk = solver.addNode();
        int amt = 350;
        Node[][] timeNodes = new Node[N][amt];
        for(int i = 0; i < N; i++) {
            for(int j = 1; j < amt; j++) {
                timeNodes[i][j] = solver.addNode();
                if (j > 1) solver.link(timeNodes[i][j-1], timeNodes[i][j], Integer.MAX_VALUE, 0);
            }
        }
        for(int i = 0; i < K; i++) {
            solver.link(src, timeNodes[people[i]][1], 1, 0);
        }
        for(int i = 1; i < amt; i++) {
            for(int j = 0; j < K; j++) {
                solver.link(timeNodes[0][i], snk, 1, C*i-C);
            }
        }
        for(int i =0; i < M; i++) {
            int a = scanner.nextInt()-1;
            int b = scanner.nextInt()-1;
            for(int j = 1; j < amt-1; j++) {
                int prev = 0;
                for(int k = 1; k <= K; k++) {
                    solver.link(timeNodes[a][j], timeNodes[b][j + 1], 1, D*k*k- prev);
                    solver.link(timeNodes[b][j], timeNodes[a][j + 1], 1, D*k*k - prev);
                    prev = D * k * k;
                }
            }
        }
        long[] ret = solver.getMinCostMaxFlow(src, snk);
        out.println(ret[1]);
        out.flush();
    }

    public static class Node {
        // thou shall not create nodes except through addNode()
        private Node() { }

        List<Edge> edges = new ArrayList<Edge>();
        int index;          // index in nodes array

    }

    public static class Edge
    {
        boolean forward; // true: edge is in original graph
        Node from, to;   // nodes connected
        long flow;        // current flow
        final long capacity;
        Edge dual;      // reference to this edge's dual
        long cost;      // only used for MinCost.
        protected Edge(Node s, Node d, long c, boolean f)
        {
            forward = f;
            from = s;
            to = d;
            capacity = c;
        }
        long remaining() { return capacity - flow; }
        void addFlow(long amount) {
            flow += amount;
            dual.flow -= amount;
        }
    }

    public static abstract class MaxFlowSolver {
        List<Node> nodes = new ArrayList<Node>();

        public void link(Node n1, Node n2, long capacity) {
            link(n1, n2, capacity, 1);
        }

        public void link(Node n1, Node n2, long capacity, long cost) {
            Edge e12 = new Edge(n1, n2, capacity, true);
            Edge e21 = new Edge(n2, n1, 0, false);
            e12.dual = e21;
            e21.dual = e12;
            n1.edges.add(e12);
            n2.edges.add(e21);
            e12.cost = cost;
            e21.cost = -cost;
        }
        void link(int n1, int n2, long capacity) {
            link(nodes.get(n1), nodes.get(n2), capacity);
        }
        protected MaxFlowSolver(int n) {
            for (int i = 0; i < n; i++)
                addNode();
        }
        protected MaxFlowSolver() {
            this(0);
        }

        public abstract long getMaxFlow(Node src, Node snk);
        public Node addNode() {
            Node n = new Node();
            n.index = nodes.size();
            nodes.add(n);
            return n;
        }
    }
    static abstract class MinCostMaxFlowSolver extends MaxFlowSolver {
        // returns [maxflow, mincost]
        abstract long [] getMinCostMaxFlow(Node src, Node snk);
        // unavoidable boiler plate
        MinCostMaxFlowSolver ()      { this(0); }
        MinCostMaxFlowSolver (int n) { super(n); }
    }

    static class EdmondsKarp extends MinCostMaxFlowSolver
    {
        EdmondsKarp ()      { this(0); }
        EdmondsKarp (int n) { super(n); }
        long minCost;

        @Override
        public long [] getMinCostMaxFlow(Node src, Node snk) {
            long maxflow = getMaxFlow(src, snk);
            return new long [] { maxflow, minCost };
        }
        static final long INF = Long.MAX_VALUE/4;

        @Override
        public long getMaxFlow(Node src, Node snk) {
            final int n = nodes.size();
            final int source = src.index;
            final int sink = snk.index;
            long flow = 0;
            long cost = 0;
            long[] potential = new long[n]; // allows Dijkstra to work with negative edge weights
            while (true) {
                Edge[] parent = new Edge[n]; // used to store an augmenting path
                long[] dist = new long[n]; // minimal cost to vertex
                Arrays.fill(dist, INF);
                dist[source] = 0;
                PriorityQueue<Item> que = new PriorityQueue<Item>();
                que.add(new Item(0, source));
                while (!que.isEmpty()) {
                    Item item = que.poll();
                    if (item.dist != dist[item.v])
                        continue;

                    for (Edge e : nodes.get(item.v).edges) {
                        long temp = dist[item.v] + e.cost + potential[item.v] - potential[e.to.index];
                        if (e.capacity > e.flow && dist[e.to.index] > temp) {
                            dist[e.to.index] = temp;
                            parent[e.to.index] = e;
                            que.add(new Item(temp, e.to.index));
                        }
                    }
                }
                if (parent[sink] == null)
                    break;
                for (int i = 0; i < n; i++)
                    if (parent[i] != null)
                        potential[i] += dist[i];
                long augFlow = Long.MAX_VALUE;
                for (int i = sink; i != source; i = parent[i].from.index)
                    augFlow = Math.min(augFlow, parent[i].capacity - parent[i].flow);
                for (int i = sink; i != source; i = parent[i].from.index) {
                    Edge e = parent[i];
                    e.addFlow(augFlow);
                    cost += augFlow * e.cost;
                }
                flow += augFlow;
            }

            minCost = cost;
            return flow;
        }

        static class Item implements Comparable<Item> {
            long dist;
            int v;

            public Item(long dist, int v) {
                this.dist = dist;
                this.v = v;
            }

            public int compareTo(Item that) {
                return Long.compare(this.dist, that.dist);
            }
        }
    }

    public static class FastScanner {
        BufferedReader br;
        StringTokenizer st;

        public FastScanner(Reader in) {
            br = new BufferedReader(in);
        }

        public FastScanner() {
            this(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String readNextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        int[] readIntArray(int n) {
            int[] a = new int[n];
            for (int idx = 0; idx < n; idx++) {
                a[idx] = nextInt();
            }
            return a;
        }
    }
}


//package educational.round67;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.List;

public class G {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), m = ni(), K = ni(), C = ni(), D = ni();
		int[] a = na(K);
		int[] from = new int[m];
		int[] to = new int[m];
		for (int i = 0; i < m; i++) {
			from[i] = ni() - 1;
			to[i] = ni() - 1;
		}
		int[][] g = packU(n, from, to);
		List<Edge> es = new ArrayList<>();

		int time = 100;
		for(int i = 0;i < n;i++){
			for(int j = 0;j < time-1;j++){
				es.add(new Edge(i*time+j, i*time+j+1, 99, C));
			}
		}
		for(int i = 0;i < n;i++){
			for(int e : g[i]){
				for(int j = 0;j < time-1;j++){
					for(int k = 0;k < n;k++){
						es.add(new Edge(i*time+j, e*time+j+1, 1, C+D*(2*k+1)));
					}
				}
			}
		}
		int src = time*n, sink = src+1;
		for(int i = 0;i < K;i++){
			es.add(new Edge(src, (a[i]-1)*time+0, 1, 0));
		}
		for(int i = 0;i < time;i++){
			es.add(new Edge(0*time+i, sink, 99, 0));
		}

		out.println(solveMinCostFlowWithSPFA(compileWD(sink+1, es), src, sink, 99));
	}

	public static class Edge
	{
		public int from, to;
		public int capacity;
		public int cost;
		public int flow;
		public Edge complement;
		// public int iniflow;

		public Edge(int from, int to, int capacity, int cost) {
			this.from = from;
			this.to = to;
			this.capacity = capacity;
			this.cost = cost;
		}
	}

	public static Edge[][] compileWD(int n, List<Edge> edges)
	{
		Edge[][] g = new Edge[n][];
		// cloning
		for(int i = edges.size()-1;i >= 0;i--){
			Edge origin = edges.get(i);
			Edge clone = new Edge(origin.to, origin.from, origin.capacity, -origin.cost);
			clone.flow = origin.capacity;
			clone.complement = origin;
			origin.complement = clone;
			edges.add(clone);
		}

		int[] p = new int[n];
		for(Edge e : edges)p[e.from]++;
		for(int i = 0;i < n;i++)g[i] = new Edge[p[i]];
		for(Edge e : edges)g[e.from][--p[e.from]] = e;
		return g;
	}

	// NOT VERIFIED
	public static Edge[][] compileWU(int n, List<Edge> edges)
	{
		Edge[][] g = new Edge[n][];
		// cloning
		for(int i = edges.size()-1;i >= 0;i--){
			Edge origin = edges.get(i);
			Edge back = new Edge(origin.to, origin.from, origin.capacity, origin.cost);
			edges.add(back);
		}
		for(int i = edges.size()-1;i >= 0;i--){
			Edge origin = edges.get(i);
			Edge clone = new Edge(origin.to, origin.from, origin.capacity, -origin.cost);
			clone.flow = origin.capacity;
			clone.complement = origin;
			origin.complement = clone;
			edges.add(clone);
		}

		int[] p = new int[n];
		for(Edge e : edges)p[e.from]++;
		for(int i = 0;i < n;i++)g[i] = new Edge[p[i]];
		for(Edge e : edges)g[e.from][--p[e.from]] = e;
		return g;
	}

	public static class DQ {
		public int[] q;
		public int n;
		protected int pt, ph;

		public DQ(int n){ this.n = Integer.highestOneBit(n)<<1; q = new int[this.n]; pt = ph = 0; }

		public void addLast(int x){ q[ph] = x; ph = ph+1&n-1; }
		public void addFirst(int x){ pt = pt+n-1&n-1; q[pt] = x; }
		public int pollFirst(){ int ret = q[pt]; pt = pt+1&n-1; return ret; }
		public int pollLast(){ ph = ph+n-1&n-1; int ret = q[ph]; return ret; }
		public int getFirst(){ return q[pt]; }
		public int getFirst(int k){ return q[pt+k&n-1]; }
		public int getLast(){ return q[ph+n-1&n-1]; }
		public int getLast(int k){ return q[ph+n-k-1&n-1]; }
		public void clear(){ pt = ph = 0; }
		public int size(){ return ph-pt+n&n-1; }
		public boolean isEmpty(){ return ph==pt; }
	}

	public static long solveMinCostFlowWithSPFA(Edge[][] g, int source, int sink, long all)
	{
		int n = g.length;
		long mincost = 0;

		final int[] d = new int[n];
		DQ q = new DQ(n);
		boolean[] inq = new boolean[n];
		while(all > 0){
			// shortest path src->sink
			Edge[] inedge = new Edge[n];
			Arrays.fill(d, Integer.MAX_VALUE / 2);
			d[source] = 0;
			q.addLast(source);
			while(!q.isEmpty()){
				int cur = q.pollFirst();
				inq[cur] = false;
				for(Edge ne : g[cur]){
					if(ne.capacity - ne.flow > 0){
						int nd = d[cur] + ne.cost;
						if(d[ne.to] > nd){
							inedge[ne.to] = ne;
							d[ne.to] = nd;
							if(!inq[ne.to]){
								q.addLast(ne.to);
								inq[ne.to] = true;
							}
						}
					}
				}
			}

			if(inedge[sink] == null)break;

			long minflow = all;
			long sumcost = 0;
			for(Edge e = inedge[sink];e != null;e = inedge[e.from]){
				if(e.capacity - e.flow < minflow)minflow = e.capacity - e.flow;
				sumcost += e.cost;
			}
			mincost += minflow * sumcost;
			for(Edge e = inedge[sink];e != null;e = inedge[e.from]){
				e.flow += minflow;
				e.complement.flow -= minflow;
			}

			all -= minflow;
		}
		return mincost;
	}

	static int[][] packU(int n, int[] from, int[] to) {
		int[][] g = new int[n][];
		int[] p = new int[n];
		for (int f : from)
			p[f]++;
		for (int t : to)
			p[t]++;
		for (int i = 0; i < n; i++)
			g[i] = new int[p[i]];
		for (int i = 0; i < from.length; i++) {
			g[from[i]][--p[from[i]]] = to[i];
			g[to[i]][--p[to[i]]] = from[i];
		}
		return g;
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new G().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


// upsolve with rainboy
import java.io.*;
import java.util.*;

public class CF1187G extends PrintWriter {
	CF1187G() { super(System.out); }
	static class Scanner {
		Scanner(InputStream in) { this.in = in; } InputStream in;
		int k, l; byte[] bb = new byte[1 << 15];
		byte getc() {
			if (k >= l) {
				k = 0;
				try { l = in.read(bb); } catch (IOException e) { l = 0; }
				if (l <= 0) return -1;
			}
			return bb[k++];
		}
		int nextInt() {
			byte c = 0; while (c <= 32) c = getc();
			int a = 0;
			while (c > 32) { a = a * 10 + c - '0'; c = getc(); }
			return a;
		}
	}
	Scanner sc = new Scanner(System.in);
	public static void main(String[] $) {
		CF1187G o = new CF1187G(); o.main(); o.flush();
	}

	static final int INF = 0x3f3f3f3f;
	ArrayList[] aa_;
	int n_, m_;
	int[] pi, dd, bb;
	int[] uu, vv, uv, cost;
	int[] cc;
	void init() {
		aa_ = new ArrayList[n_];
		for (int u = 0; u < n_; u++)
			aa_[u] = new ArrayList<Integer>();
		pi = new int[n_];
		dd = new int[n_];
		bb = new int[n_];
		qq = new int[nq];
		iq = new boolean[n_];
		uu = new int[m_];
		vv = new int[m_];
		uv = new int[m_];
		cost = new int[m_];
		cc = new int[m_ * 2];
		m_ = 0;
	}
	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;
		aa_[u].add(h << 1 ^ 0);
		aa_[v].add(h << 1 ^ 1);
	}
	int[] qq;
	int nq = 1 << 20, head, cnt;
	boolean[] iq;
	void enqueue(int v) {
		if (iq[v])
			return;
		if (head + cnt == nq) {
			if (cnt * 4 <= nq)
				System.arraycopy(qq, head, qq, 0, cnt);
			else {
				int[] qq_ = new int[nq *= 2];
				System.arraycopy(qq, head, qq_, 0, cnt);
				qq = qq_;
			}
			head = 0;
		}
		qq[head + cnt++] = v; iq[v] = true;
	}
	int dequeue() {
		int u = qq[head++]; cnt--; iq[u] = false;
		return u;
	}
	boolean spfa(int s, int t) {
		Arrays.fill(pi, INF);
		pi[s] = 0;
		head = cnt = 0;
		enqueue(s);
		while (cnt > 0) {
			int u = dequeue();
			int d = dd[u] + 1;
			ArrayList<Integer> adj = aa_[u];
			for (int h_ : adj)
				if (cc[h_] > 0) {
					int h = h_ >> 1;
					int p = pi[u] + ((h_ & 1) == 0 ? cost[h] : -cost[h]);
					int v = u ^ uv[h];
					if (pi[v] > p || pi[v] == p && dd[v] > d) {
						pi[v] = p;
						dd[v] = d;
						bb[v] = h_;
						enqueue(v);
					}
				}
		}
		return pi[t] != INF;
	}
	void push(int s, int t) {
		int c = INF;
		for (int u = t, h_, h; u != s; u ^= uv[h]) {
			h = (h_ = bb[u]) >> 1;
			c = Math.min(c, cc[h_]);
		}
		for (int u = t, h_, h; u != s; u ^= uv[h]) {
			h = (h_ = bb[u]) >> 1;
			cc[h_] -= c; cc[h_ ^ 1] += c;
		}
	}
	void push1(int s, int t) {
		for (int u = t, h_, h; u != s; u ^= uv[h]) {
			h = (h_ = bb[u]) >> 1;
			cc[h_]--; cc[h_ ^ 1]++;
		}
	}
	int edmonds_karp(int s, int t) {
		while (spfa(s, t))
			push1(s, t);
		int c = 0;
		for (int h = 0; h < m_; h++)
			c += cost[h] * cc[h << 1 ^ 1];
		return c;
	}
	void main() {
		int n = sc.nextInt();
		int m = sc.nextInt();
		int k = sc.nextInt();
		int c = sc.nextInt();
		int d = sc.nextInt();
		int[] ii = new int[k];
		for (int h = 0; h < k; h++)
			ii[h] = sc.nextInt() - 1;
		ArrayList[] aa = new ArrayList[n];
		for (int i = 0; i < n; i++)
			aa[i] = new ArrayList<Integer>();
		for (int h = 0; h < m; h++) {
			int i = sc.nextInt() - 1;
			int j = sc.nextInt() - 1;
			aa[i].add(j);
			aa[j].add(i);
		}
		int t = n + k + 1;
		n_ = n * t + 1;
		m_ = k + (m * 2 * k + n) * (t - 1);
		init();
		for (int i = 0; i < n; i++) {
			ArrayList<Integer> adj = aa[i];
			for (int s = 0; s < t - 1; s++) {
				int u = i * t + s;
				for (int j : adj) {
					int v = j * t + s + 1;
					for (int x = 1; x <= k; x++)
						link(u, v, 1, c + (x * 2 - 1) * d);
				}
			}
		}
		for (int i = 0; i < n; i++)
			for (int s = 0; s < t - 1; s++) {
				int u = i * t + s, v = u + 1;
				link(u, v, k, i == 0 ? 0 : c);
			}
		for (int h = 0; h < k; h++)
			link(n_ - 1, ii[h] * t + 0, 1, 0);
		println(edmonds_karp(n_ - 1, 0 * t + t - 1));
	}
}


import java.io.*;
import java.util.*;
public class G{
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskE solver = new TaskE();
        solver.solve(1, in, out);
        out.flush();out.close();
    }
        static class TaskE {
        class MinCostMaxFlow{
                ArrayList<Edge> al[];
                Edge ja[][];
                int d[]; // shortest distances
                int N , S , T , maxFlow ; int minCost;
                final int gmax = Integer.MAX_VALUE / 100;

                int edges = 0;

                class Edge{
                    int u , flow, rid, cost;
                    Edge(int a, int b, int c, int d){u = a; flow = b; cost = c; rid = d;}
                }

                void addEdge(int u , int v , int flow , int cost){
                    int lu = al[u].size(), lv = al[v].size();
                    al[u].add(new Edge(v, flow, cost, lv));
                    al[v].add(new Edge(u, 0, -cost, lu));
                }

                void convertToArray(){
                    ja = new Edge[N][];
                    for(int i = 0; i < N; i++){
                        int sz = al[i].size();
                        ja[i] = new Edge[sz];
                        for(int j = 0; j < sz; j++){
                            ja[i][j] = al[i].get(j);
                        }
                        al[i].clear();
                    }
                }

                MinCostMaxFlow(int n , int source , int sink){
                    N = n; S = source; T = sink; maxFlow = 0; minCost = 0;
                    al = new ArrayList[N];
                    d = new int[N];
                    for(int i = 0; i < N; i++){
                        al[i] = new ArrayList<>();
                    }
                }

                boolean BellmanFord(boolean check){
                    d[0] = 0;
                    for(int i = 0; i < N - 1; i++){
                        for(int j = 0; j < N; j++){
                            for(Edge e : ja[j]){
                                if(e.flow == 0)continue; // not to consider reverse edges
                                d[e.u] = Math.min(d[e.u] , d[j] + e.cost);
                            }
                        }
                    }
                    if(check){// check for negative cycles
                        for(int j = 0; j < N; j++){
                            for(Edge e : ja[j]){
                                if(e.flow == 0)continue;
                                if(d[j] + e.cost < d[e.u]) return false;
                            }
                        }
                    }return true;
                }

                int node[]; // present node

                int visit[]; // 0 -> not added 1 -> not removed 2 -> removed
                int prv[], prve[]; // previous node for augmentation
                int dist[]; // min dist

                boolean simple(){
                    node = new int[N];
                    visit = new int[N];
                    prv = new int[N];
                    prve = new int[N];
                    dist = new int[N];   Arrays.fill(dist , gmax);

                    node[0] = S; dist[0] = 0;
                    int front = 1, back = 0;
                    while(front != back){
                        int u = node[back++]; int distu = dist[u];
                        if(back == N)back = 0;
                        visit[u] = 2;
                        for(int i = 0; i < ja[u].length; i++){
                            Edge e = ja[u][i];
                            if(e.flow == 0)continue;
                            int cdist = distu + e.cost; // no need of reduced cost
                            if(cdist < dist[e.u]){
                                if(visit[e.u] == 0){
                                    node[front] = e.u;
                                    if(++front == N)front = 0;
                                }else if(visit[e.u] == 2){
                                    if(--back == -1)back += N;
                                    node[back] = e.u;
                                }
                                visit[e.u] = 1;
                                prve[e.u] = i; prv[e.u] = u; dist[e.u] = cdist;
                            }
                        }
                    }
                    return visit[T] != 0;
                }

                class pair{
                    int F; int S;
                    pair(int a, int b){F = a; S = b;}
                }

                boolean dijkstra(){
                    visit = new int[N];
                    prv = new int[N];
                    prve = new int[N];
                    dist = new int[N]; Arrays.fill(dist, gmax);
                    PriorityQueue<pair> pq = new PriorityQueue<>((A, B) -> Double.compare(A.S , B.S));

                    pq.add(new pair(S , 0)); dist[0] = 0;
                    o : while(!pq.isEmpty()){
                        pair p = pq.poll();
                        while(dist[p.F] < p.S){
                            if(pq.isEmpty()) break o; // had a better val
                            p = pq.poll();
                        }
                        visit[p.F] = 2;
                        for(int i = 0; i < ja[p.F].length; i++){
                            Edge e = ja[p.F][i];
                            if(e.flow == 0)continue; // important
                            int cdist = p.S + (e.cost + d[p.F] - d[e.u]); // reduced cost
                            if(cdist < dist[e.u]){
                                if(visit[e.u] == 2) return false;
                                pq.add(new pair(e.u , cdist));
                                dist[e.u] = cdist; prv[e.u] = p.F; prve[e.u] = i;
                                visit[e.u] = 1;
                            }
                        }
                    }
                    return visit[T] != 0;
                }

                int augment(){
                    int p = T; int min = gmax;
                    while(p != 0){
                        int pp = prv[p], pe = prve[p];
                        int val = ja[pp][pe].flow;
                        min = Math.min(min , val);
                        p = pp;
                    }
                    p = T;
                    while(p != 0){
                        int pp = prv[p], pe = prve[p];
                        ja[pp][pe].flow -= min;
                        ja[p][ja[pp][pe].rid].flow += min;
                        p = pp;
                    }
                    maxFlow += min;
                    return min;
                }

                // if(dist[T] >= 0)return true; // non contributing flow
                boolean calSimple(){
                    // uncomment to check for negative cycles
                    /* boolean possible = BellmanFord(true);
                     if(!possible) return false; */
                    while(simple()){
                        /*if(dist[T] >= 0)return true;*/
                        minCost += dist[T] * augment();
                    }
                    return true;
                }

                void updPotential(){
                    for(int i = 0; i < N; i++){
                        if(visit[i] != 0){
                            d[i] += dist[i] - dist[S];
                        }
                    }
                }
                boolean calWithPotential(){
                    // set true to check for negative cycles
                    // boolean possible = BellmanFord(false);
                    // if(!possible) return false;
                    while(dijkstra()){
                        int min = dist[T] + d[T] - d[S]; // getting back the original cost
                        /*if(dist[T] >= 0)return true;*/
                        minCost += min * augment();
                        updPotential();
                    }
                    return true;
                }
            }
            int n , m, k, c, d, a[], f[];
           public void solve(int testNumber, InputReader in, PrintWriter out) {
            n = in.nextInt(); m = in.nextInt(); k = in.nextInt(); c = in.nextInt(); d= in.nextInt();
            // S + n
            int maxl = n + k, T = n * maxl + 1;
            MinCostMaxFlow ans = new MinCostMaxFlow(T + 1, 0, T);
            a = new int[k + 1]; f = new int[n + 1];
            for(int i = 1; i <= k; i++){
                a[i] = in.nextInt();
                f[a[i]]++;
            }
            for(int i = 1; i <= n; i++){
                if(f[i] == 0)continue;
                ans.addEdge(0 , i , f[i], 0);
            }
            for(int i = 2; i <= n; i++){
                for(int l = 0; l < maxl - 1; l++){
                    ans.addEdge(l * n + i , (l + 1) * n + i, k, c);
                }
            }
            for(int i = 1; i <= m; i++){
                int a = in.nextInt(), b = in.nextInt();
                for(int l = 0; l < maxl - 1; l++){
                    for(int p = 1; p <= k; p++){
                        if(a != 1)
                            ans.addEdge(n * l + a, n * (l + 1) + b, 1, d * (2 * p - 1) + c);
                        if(b != 1)
                            ans.addEdge(n * l + b, n * (l + 1) + a, 1, d * (2 * p - 1) + c);
                    }
                }
            }
            for(int l = 1; l < maxl; l++){
                ans.addEdge(l * n + 1, T, k, 0);
            }
            ans.convertToArray();
            ans.calWithPotential();
            // ans.calSimple();
            if(ans.maxFlow != k){
                out.println("BUG");
            }else{
                out.println((int)ans.minCost);
            }
          }
    }
    static class InputReader {
        BufferedReader br;
        StringTokenizer st;
        public InputReader(InputStream stream) {
            br = new BufferedReader(new InputStreamReader(stream));
            st = null;
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return null;
                st = new StringTokenizer(s);
            }
            return st.nextToken();
        }

        boolean hasMoreTokens() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return false;
                st = new StringTokenizer(s);
            }
            return true;
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }
        public long nextLong() {
            return Long.parseLong(next());
        }
        public double nextDouble() {
            return Double.parseDouble(next());
        }
    }
}


// upsolve with rainboy
import java.io.*;
import java.util.*;

public class CF1187G extends PrintWriter {
	CF1187G() { super(System.out, true); }
	static class Scanner {
		Scanner(InputStream in) { this.in = in; } InputStream in;
		int k, l; byte[] bb = new byte[1 << 15];
		byte getc() {
			if (k >= l) {
				k = 0;
				try { l = in.read(bb); } catch (IOException e) { l = 0; }
				if (l <= 0) return -1;
			}
			return bb[k++];
		}
		int nextInt() {
			byte c = 0; while (c <= 32) c = getc();
			int a = 0;
			while (c > 32) { a = a * 10 + c - '0'; c = getc(); }
			return a;
		}
	}
	Scanner sc = new Scanner(System.in);
	public static void main(String[] $) {
		CF1187G o = new CF1187G(); o.main(); o.flush();
	}

	static final int INF = 0x3f3f3f3f;
	ArrayList[] aa_;
	int n_, m_;
	int[] pi, kk;
	int[] uu, vv, uv, cost, cost_;
	int[] cc;
	void init() {
		aa_ = new ArrayList[n_];
		for (int u = 0; u < n_; u++)
			aa_[u] = new ArrayList<Integer>();
		pi = new int[n_];
		kk = new int[n_];
		uu = new int[m_];
		vv = new int[m_];
		uv = new int[m_];
		cost = new int[m_];
		cc = new int[m_ * 2];
		m_ = 0;
	}
	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;
		aa_[u].add(h << 1 ^ 0);
		aa_[v].add(h << 1 ^ 1);
	}
	boolean dijkstra(int s, int t) {
		Arrays.fill(pi, INF);
		pi[s] = 0;
		TreeSet<Integer> pq = new TreeSet<>((u, v) -> pi[u] != pi[v] ? pi[u] - pi[v] : kk[u] != kk[v] ? kk[u] - kk[v] : u - v);
		pq.add(s);
		Integer first;
		while ((first = pq.pollFirst()) != null) {
			int u = first;
			int k = kk[u] + 1;
			ArrayList<Integer> adj = aa_[u];
			for (int h_ : adj)
				if (cc[h_] > 0) {
					int h = h_ >> 1;
					int p = pi[u] + ((h_ & 1) == 0 ? cost_[h] : -cost_[h]);
					int v = u ^ uv[h];
					if (pi[v] > p || pi[v] == p && kk[v] > k) {
						if (pi[v] != INF)
							pq.remove(v);
						pi[v] = p;
						kk[v] = k;
						pq.add(v);
					}
				}
		}
		return pi[t] != INF;
	}
	int dfs(int u, int t, int c) {
		if (u == t || c == 0)
			return c;
		int k = kk[u] + 1;
		ArrayList<Integer> adj = aa_[u];
		for (int h_ : adj) {
			int h = h_ >> 1;
			int v = u ^ uv[h];
			if (kk[v] != k)
				continue;
			int p = pi[u] + ((h_ & 1) == 0 ? cost_[h] : -cost_[h]), f;
			if (pi[v] == p && (f = dfs(v, t, Math.min(c, cc[h_]))) != 0) {
				cc[h_] -= f; cc[h_ ^ 1] += f;
				return f;
			}
		}
		kk[u] = INF;
		return 0;
	}
	int edmonds_karp(int s, int t) {
		cost_ = Arrays.copyOf(cost, m_);
		while (dijkstra(s, t)) {
			while (dfs(s, t, INF) > 0)
				;
			for (int 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];
			}
		}
		int c = 0;
		for (int h = 0; h < m_; h++)
			c += cost[h] * cc[h << 1 ^ 1];
		return c;
	}
	void main() {
		int n = sc.nextInt();
		int m = sc.nextInt();
		int k = sc.nextInt();
		int c = sc.nextInt();
		int d = sc.nextInt();
		int[] ii = new int[k];
		for (int h = 0; h < k; h++)
			ii[h] = sc.nextInt() - 1;
		ArrayList[] aa = new ArrayList[n];
		for (int i = 0; i < n; i++)
			aa[i] = new ArrayList<Integer>();
		for (int h = 0; h < m; h++) {
			int i = sc.nextInt() - 1;
			int j = sc.nextInt() - 1;
			aa[i].add(j);
			aa[j].add(i);
		}
		int t = n + k + 1;
		n_ = n * t + 1;
		m_ = k + (m * 2 * k + n) * (t - 1);
		init();
		for (int i = 0; i < n; i++) {
			ArrayList<Integer> adj = aa[i];
			for (int s = 0; s < t - 1; s++) {
				int u = i * t + s;
				for (int j : adj) {
					int v = j * t + s + 1;
					for (int x = 1; x <= k; x++)
						link(u, v, 1, c + (x * 2 - 1) * d);
				}
			}
		}
		for (int i = 0; i < n; i++)
			for (int s = 0; s < t - 1; s++) {
				int u = i * t + s, v = u + 1;
				link(u, v, k, i == 0 ? 0 : c);
			}
		for (int h = 0; h < k; h++)
			link(n_ - 1, ii[h] * t + 0, 1, 0);
		println(edmonds_karp(n_ - 1, 0 * t + t - 1));
	}
}


import java.io.*;
import java.util.*;
public class G{
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskE solver = new TaskE();
        solver.solve(1, in, out);
        out.flush();out.close();
    }
        static class TaskE {
        class MinCostMaxFlow{
                ArrayList<Edge> al[];
                Edge ja[][];
                int d[]; // shortest distances
                int N , S , T , maxFlow ; int minCost;
                final int gmax = Integer.MAX_VALUE / 100;

                int edges = 0;

                class Edge{
                    int u , flow, rid, cost;
                    Edge(int a, int b, int c, int d){u = a; flow = b; cost = c; rid = d;}
                }

                void addEdge(int u , int v , int flow , int cost){
                    int lu = al[u].size(), lv = al[v].size();
                    al[u].add(new Edge(v, flow, cost, lv));
                    al[v].add(new Edge(u, 0, -cost, lu));
                }

                void convertToArray(){
                    ja = new Edge[N][];
                    for(int i = 0; i < N; i++){
                        int sz = al[i].size();
                        ja[i] = new Edge[sz];
                        for(int j = 0; j < sz; j++){
                            ja[i][j] = al[i].get(j);
                        }
                        al[i].clear();
                    }
                }

                MinCostMaxFlow(int n , int source , int sink){
                    N = n; S = source; T = sink; maxFlow = 0; minCost = 0;
                    al = new ArrayList[N];
                    d = new int[N];
                    for(int i = 0; i < N; i++){
                        al[i] = new ArrayList<>();
                    }
                }

                boolean BellmanFord(boolean check){
                    d[0] = 0;
                    for(int i = 0; i < N - 1; i++){
                        for(int j = 0; j < N; j++){
                            for(Edge e : ja[j]){
                                if(e.flow == 0)continue; // not to consider reverse edges
                                d[e.u] = Math.min(d[e.u] , d[j] + e.cost);
                            }
                        }
                    }
                    if(check){// check for negative cycles
                        for(int j = 0; j < N; j++){
                            for(Edge e : ja[j]){
                                if(e.flow == 0)continue;
                                if(d[j] + e.cost < d[e.u]) return false;
                            }
                        }
                    }return true;
                }

                int node[]; // present node

                int visit[]; // 0 -> not added 1 -> not removed 2 -> removed
                int prv[], prve[]; // previous node for augmentation
                int dist[]; // min dist

                boolean simple(){
                    node = new int[N];
                    visit = new int[N];
                    prv = new int[N];
                    prve = new int[N];
                    dist = new int[N];   Arrays.fill(dist , gmax);

                    node[0] = S; dist[0] = 0;
                    int front = 1, back = 0;
                    while(front != back){
                        int u = node[back++]; int distu = dist[u];
                        if(back == N)back = 0;
                        visit[u] = 2;
                        for(int i = 0; i < ja[u].length; i++){
                            Edge e = ja[u][i];
                            if(e.flow == 0)continue;
                            int cdist = distu + e.cost; // no need of reduced cost
                            if(cdist < dist[e.u]){
                                if(visit[e.u] == 0){
                                    node[front] = e.u;
                                    if(++front == N)front = 0;
                                }else if(visit[e.u] == 2){
                                    if(--back == -1)back += N;
                                    node[back] = e.u;
                                }
                                visit[e.u] = 1;
                                prve[e.u] = i; prv[e.u] = u; dist[e.u] = cdist;
                            }
                        }
                    }
                    return visit[T] != 0;
                }

                class pair{
                    int F; int S;
                    pair(int a, int b){F = a; S = b;}
                }

                boolean dijkstra(){
                    visit = new int[N];
                    prv = new int[N];
                    prve = new int[N];
                    dist = new int[N]; Arrays.fill(dist, gmax);
                    PriorityQueue<pair> pq = new PriorityQueue<>((A, B) -> Double.compare(A.S , B.S));

                    pq.add(new pair(S , 0)); dist[0] = 0;
                    o : while(!pq.isEmpty()){
                        pair p = pq.poll();
                        while(dist[p.F] < p.S){
                            if(pq.isEmpty()) break o; // had a better val
                            p = pq.poll();
                        }
                        visit[p.F] = 2;
                        for(int i = 0; i < ja[p.F].length; i++){
                            Edge e = ja[p.F][i];
                            if(e.flow == 0)continue; // important
                            int cdist = p.S + (e.cost + d[p.F] - d[e.u]); // reduced cost
                            if(cdist < dist[e.u]){
                                if(visit[e.u] == 2) return false;
                                pq.add(new pair(e.u , cdist));
                                dist[e.u] = cdist; prv[e.u] = p.F; prve[e.u] = i;
                                visit[e.u] = 1;
                            }
                        }
                    }
                    return visit[T] != 0;
                }

                int augment(){
                    int p = T; int min = gmax;
                    while(p != 0){
                        int pp = prv[p], pe = prve[p];
                        int val = ja[pp][pe].flow;
                        min = Math.min(min , val);
                        p = pp;
                    }
                    p = T;
                    while(p != 0){
                        int pp = prv[p], pe = prve[p];
                        ja[pp][pe].flow -= min;
                        ja[p][ja[pp][pe].rid].flow += min;
                        p = pp;
                    }
                    maxFlow += min;
                    return min;
                }

                // if(dist[T] >= 0)return true; // non contributing flow
                boolean calSimple(){
                    // uncomment to check for negative cycles
                    /* boolean possible = BellmanFord(true);
                     if(!possible) return false; */
                    while(simple()){
                        /*if(dist[T] >= 0)return true;*/
                        minCost += dist[T] * augment();
                    }
                    return true;
                }

                void updPotential(){
                    for(int i = 0; i < N; i++){
                        if(visit[i] != 0){
                            d[i] += dist[i] - dist[S];
                        }
                    }
                }
                boolean calWithPotential(){
                    // set true to check for negative cycles
                    // boolean possible = BellmanFord(false);
                    // if(!possible) return false;
                    while(dijkstra()){
                        int min = dist[T] + d[T] - d[S]; // getting back the original cost
                        /*if(dist[T] >= 0)return true;*/
                        minCost += min * augment();
                        updPotential();
                    }
                    return true;
                }
            }
            int n , m, k, c, d, a[], f[];
           public void solve(int testNumber, InputReader in, PrintWriter out) {
            n = in.nextInt(); m = in.nextInt(); k = in.nextInt(); c = in.nextInt(); d= in.nextInt();
            // S + n
            int maxl = n + k, T = n * maxl + 1;
            MinCostMaxFlow ans = new MinCostMaxFlow(T + 1, 0, T);
            a = new int[k + 1]; f = new int[n + 1];
            for(int i = 1; i <= k; i++){
                a[i] = in.nextInt();
                f[a[i]]++;
            }
            for(int i = 1; i <= n; i++){
                if(f[i] == 0)continue;
                ans.addEdge(0 , i , f[i], 0);
            }
            for(int i = 2; i <= n; i++){
                for(int l = 0; l < maxl - 1; l++){
                    ans.addEdge(l * n + i , (l + 1) * n + i, k, c);
                }
            }
            for(int i = 1; i <= m; i++){
                int a = in.nextInt(), b = in.nextInt();
                for(int l = 0; l < maxl - 1; l++){
                    for(int p = 1; p <= k; p++){
                        if(a != 1)
                            ans.addEdge(n * l + a, n * (l + 1) + b, 1, d * (2 * p - 1) + c);
                        if(b != 1)
                            ans.addEdge(n * l + b, n * (l + 1) + a, 1, d * (2 * p - 1) + c);
                    }
                }
            }
            for(int l = 1; l < maxl; l++){
                ans.addEdge(l * n + 1, T, k, 0);
            }
            ans.convertToArray();
            // ans.calWithPotential();
            ans.calSimple();
            if(ans.maxFlow != k){
                out.println("BUG");
            }else{
                out.println((int)ans.minCost);
            }
          }
    }
    static class InputReader {
        BufferedReader br;
        StringTokenizer st;
        public InputReader(InputStream stream) {
            br = new BufferedReader(new InputStreamReader(stream));
            st = null;
        }

        String next() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return null;
                st = new StringTokenizer(s);
            }
            return st.nextToken();
        }

        boolean hasMoreTokens() {
            while (st == null || !st.hasMoreTokens()) {
                String s = null;
                try {
                    s = br.readLine();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (s == null)
                    return false;
                st = new StringTokenizer(s);
            }
            return true;
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }
        public long nextLong() {
            return Long.parseLong(next());
        }
        public double nextDouble() {
            return Double.parseDouble(next());
        }
    }
}


// upsolve with rainboy
import java.io.*;
import java.util.*;

public class CF1187G extends PrintWriter {
	CF1187G() { super(System.out); }
	static class Scanner {
		Scanner(InputStream in) { this.in = in; } InputStream in;
		int k, l; byte[] bb = new byte[1 << 15];
		byte getc() {
			if (k >= l) {
				k = 0;
				try { l = in.read(bb); } catch (IOException e) { l = 0; }
				if (l <= 0) return -1;
			}
			return bb[k++];
		}
		int nextInt() {
			byte c = 0; while (c <= 32) c = getc();
			int a = 0;
			while (c > 32) { a = a * 10 + c - '0'; c = getc(); }
			return a;
		}
	}
	Scanner sc = new Scanner(System.in);
	public static void main(String[] $) {
		CF1187G o = new CF1187G(); o.main(); o.flush();
	}

	static final int INF = 0x3f3f3f3f;
	ArrayList[] aa_;
	int n_, m_;
	int[] pi, bb;
	int[] uu, vv, uv, cost;
	int[] cc;
	void init() {
		aa_ = new ArrayList[n_];
		for (int u = 0; u < n_; u++)
			aa_[u] = new ArrayList<Integer>();
		pi = new int[n_];
		bb = new int[n_];
		qq = new int[nq];
		iq = new boolean[n_];
		uu = new int[m_];
		vv = new int[m_];
		uv = new int[m_];
		cost = new int[m_];
		cc = new int[m_ * 2];
		m_ = 0;
	}
	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;
		aa_[u].add(h << 1 ^ 0);
		aa_[v].add(h << 1 ^ 1);
	}
	int[] qq;
	int nq = 1 << 20, head, cnt;
	boolean[] iq;
	void enqueue(int v) {
		if (iq[v])
			return;
		if (head + cnt == nq) {
			if (cnt * 2 <= nq)
				System.arraycopy(qq, head, qq, 0, cnt);
			else {
				int[] qq_ = new int[nq *= 2];
				System.arraycopy(qq, head, qq_, 0, cnt);
				qq = qq_;
			}
			head = 0;
		}
		qq[head + cnt++] = v; iq[v] = true;
	}
	int dequeue() {
		int u = qq[head++]; cnt--; iq[u] = false;
		return u;
	}
	boolean spfa(int s, int t) {
		Arrays.fill(pi, INF);
		pi[s] = 0;
		head = cnt = 0;
		enqueue(s);
		while (cnt > 0) {
			int u = dequeue();
			ArrayList<Integer> adj = aa_[u];
			for (int h_ : adj)
				if (cc[h_] > 0) {
					int h = h_ >> 1;
					int p = pi[u] + ((h_ & 1) == 0 ? cost[h] : -cost[h]);
					int v = u ^ uv[h];
					if (pi[v] > p) {
						pi[v] = p;
						bb[v] = h_;
						enqueue(v);
					}
				}
		}
		return pi[t] != INF;
	}
	void push(int s, int t) {
		int c = INF;
		for (int u = t, h_, h; u != s; u ^= uv[h]) {
			h = (h_ = bb[u]) >> 1;
			c = Math.min(c, cc[h_]);
		}
		for (int u = t, h_, h; u != s; u ^= uv[h]) {
			h = (h_ = bb[u]) >> 1;
			cc[h_] -= c; cc[h_ ^ 1] += c;
		}
	}
	void push1(int s, int t) {
		for (int u = t, h_, h; u != s; u ^= uv[h]) {
			h = (h_ = bb[u]) >> 1;
			cc[h_]--; cc[h_ ^ 1]++;
		}
	}
	int edmonds_karp(int s, int t) {
		while (spfa(s, t))
			push1(s, t);
		int c = 0;
		for (int h = 0; h < m_; h++)
			c += cost[h] * cc[h << 1 ^ 1];
		return c;
	}
	void main() {
		int n = sc.nextInt();
		int m = sc.nextInt();
		int k = sc.nextInt();
		int c = sc.nextInt();
		int d = sc.nextInt();
		int[] ii = new int[k];
		for (int h = 0; h < k; h++)
			ii[h] = sc.nextInt() - 1;
		ArrayList[] aa = new ArrayList[n];
		for (int i = 0; i < n; i++)
			aa[i] = new ArrayList<Integer>();
		for (int h = 0; h < m; h++) {
			int i = sc.nextInt() - 1;
			int j = sc.nextInt() - 1;
			aa[i].add(j);
			aa[j].add(i);
		}
		int t = n + k + 1;
		n_ = n * t + 1;
		m_ = k + (m * 2 * k + n) * (t - 1);
		init();
		for (int i = 0; i < n; i++) {
			ArrayList<Integer> adj = aa[i];
			for (int s = 0; s < t - 1; s++) {
				int u = i * t + s;
				for (int j : adj) {
					int v = j * t + s + 1;
					for (int x = 1; x <= k; x++)
						link(u, v, 1, c + (x * 2 - 1) * d);
				}
			}
		}
		for (int i = 0; i < n; i++)
			for (int s = 0; s < t - 1; s++) {
				int u = i * t + s, v = u + 1;
				link(u, v, k, i == 0 ? 0 : c);
			}
		for (int h = 0; h < k; h++)
			link(n_ - 1, ii[h] * t + 0, 1, 0);
		println(edmonds_karp(n_ - 1, 0 * t + t - 1));
	}
}


// upsolve with rainboy
import java.io.*;
import java.util.*;

public class CF1187G extends PrintWriter {
	CF1187G() { super(System.out); }
	static class Scanner {
		Scanner(InputStream in) { this.in = in; } InputStream in;
		int k, l; byte[] bb = new byte[1 << 15];
		byte getc() {
			if (k >= l) {
				k = 0;
				try { l = in.read(bb); } catch (IOException e) { l = 0; }
				if (l <= 0) return -1;
			}
			return bb[k++];
		}
		int nextInt() {
			byte c = 0; while (c <= 32) c = getc();
			int a = 0;
			while (c > 32) { a = a * 10 + c - '0'; c = getc(); }
			return a;
		}
	}
	Scanner sc = new Scanner(System.in);
	public static void main(String[] $) {
		CF1187G o = new CF1187G(); o.main(); o.flush();
	}

	static final int INF = 0x3f3f3f3f;
	ArrayList[] aa_;
	int n_, m_;
	int[] pi, kk, bb;
	int[] uu, vv, uv, cost, cost_;
	int[] cc;
	void init() {
		aa_ = new ArrayList[n_];
		for (int u = 0; u < n_; u++)
			aa_[u] = new ArrayList<Integer>();
		pi = new int[n_];
		kk = new int[n_];
		bb = new int[n_];
		uu = new int[m_];
		vv = new int[m_];
		uv = new int[m_];
		cost = new int[m_];
		cost_ = new int[m_];
		cc = new int[m_ * 2];
		m_ = 0;
	}
	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;
		aa_[u].add(h << 1 ^ 0);
		aa_[v].add(h << 1 ^ 1);
	}
	boolean dijkstra(int s, int t) {
		Arrays.fill(pi, INF);
		pi[s] = 0;
		TreeSet<Integer> pq = new TreeSet<>((u, v) -> pi[u] != pi[v] ? pi[u] - pi[v] : kk[u] != kk[v] ? kk[u] - kk[v] : u - v);
		pq.add(s);
		Integer first;
		while ((first = pq.pollFirst()) != null) {
			int u = first;
			int k = kk[u] + 1;
			ArrayList<Integer> adj = aa_[u];
			for (int h_ : adj)
				if (cc[h_] > 0) {
					int h = h_ >> 1;
					int p = pi[u] + ((h_ & 1) == 0 ? cost_[h] : -cost_[h]);
					int v = u ^ uv[h];
					if (pi[v] > p || pi[v] == p && kk[v] > k) {
						if (pi[v] != INF)
							pq.remove(v);
						pi[v] = p;
						kk[v] = k;
						bb[v] = h_;
						pq.add(v);
					}
				}
		}
		return pi[t] != INF;
	}
	void push(int s, int t) {
		int c = INF;
		for (int u = t, h_, h; u != s; u ^= uv[h]) {
			h = (h_ = bb[u]) >> 1;
			c = Math.min(c, cc[h_]);
		}
		for (int u = t, h_, h; u != s; u ^= uv[h]) {
			h = (h_ = bb[u]) >> 1;
			cc[h_] -= c; cc[h_ ^ 1] += c;
		}
	}
	void push1(int s, int t) {
		for (int u = t, h_, h; u != s; u ^= uv[h]) {
			h = (h_ = bb[u]) >> 1;
			cc[h_]--; cc[h_ ^ 1]++;
		}
	}
	int edmonds_karp(int s, int t) {
		System.arraycopy(cost, 0, cost_, 0, m_);
		while (dijkstra(s, t)) {
			push1(s, t);
			for (int 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];
			}
		}
		int c = 0;
		for (int h = 0; h < m_; h++)
			c += cost[h] * cc[h << 1 ^ 1];
		return c;
	}
	void main() {
		int n = sc.nextInt();
		int m = sc.nextInt();
		int k = sc.nextInt();
		int c = sc.nextInt();
		int d = sc.nextInt();
		int[] ii = new int[k];
		for (int h = 0; h < k; h++)
			ii[h] = sc.nextInt() - 1;
		ArrayList[] aa = new ArrayList[n];
		for (int i = 0; i < n; i++)
			aa[i] = new ArrayList<Integer>();
		for (int h = 0; h < m; h++) {
			int i = sc.nextInt() - 1;
			int j = sc.nextInt() - 1;
			aa[i].add(j);
			aa[j].add(i);
		}
		int t = n + k + 1;
		n_ = n * t + 1;
		m_ = k + (m * 2 * k + n) * (t - 1);
		init();
		for (int i = 0; i < n; i++) {
			ArrayList<Integer> adj = aa[i];
			for (int s = 0; s < t - 1; s++) {
				int u = i * t + s;
				for (int j : adj) {
					int v = j * t + s + 1;
					for (int x = 1; x <= k; x++)
						link(u, v, 1, c + (x * 2 - 1) * d);
				}
			}
		}
		for (int i = 0; i < n; i++)
			for (int s = 0; s < t - 1; s++) {
				int u = i * t + s, v = u + 1;
				link(u, v, k, i == 0 ? 0 : c);
			}
		for (int h = 0; h < k; h++)
			link(n_ - 1, ii[h] * t + 0, 1, 0);
		println(edmonds_karp(n_ - 1, 0 * t + t - 1));
	}
}


import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.InputMismatchException;
import java.util.List;

public class G {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), m = ni(), K = ni(), C = ni(), D = ni();
		int[] a = na(K);
		int[] from = new int[m];
		int[] to = new int[m];
		for (int i = 0; i < m; i++) {
			from[i] = ni() - 1;
			to[i] = ni() - 1;
		}
		int[][] g = packU(n, from, to);
		List<Edge> es = new ArrayList<>();

		int time = 100;
		for(int i = 0;i < n;i++){
			for(int j = 0;j < time-1;j++){
				es.add(new Edge(i*time+j, i*time+j+1, 99, C));
			}
		}
		for(int i = 0;i < n;i++){
			for(int e : g[i]){
				for(int j = 0;j < time-1;j++){
					for(int k = 0;k < n;k++){
						es.add(new Edge(i*time+j, e*time+j+1, 1, C+D*(2*k+1)));
					}
				}
			}
		}
		int src = time*n, sink = src+1;
		for(int i = 0;i < K;i++){
			es.add(new Edge(src, (a[i]-1)*time+0, 1, 0));
		}
		for(int i = 0;i < time;i++){
			es.add(new Edge(0*time+i, sink, 99, 0));
		}

		out.println(solveMinCostFlowWithSPFA(compileWD(sink+1, es), src, sink, 99));
	}

	public static class Edge
	{
		public int from, to;
		public int capacity;
		public int cost;
		public int flow;
		public Edge complement;
		// public int iniflow;

		public Edge(int from, int to, int capacity, int cost) {
			this.from = from;
			this.to = to;
			this.capacity = capacity;
			this.cost = cost;
		}
	}

	public static Edge[][] compileWD(int n, List<Edge> edges)
	{
		Edge[][] g = new Edge[n][];
		// cloning
		for(int i = edges.size()-1;i >= 0;i--){
			Edge origin = edges.get(i);
			Edge clone = new Edge(origin.to, origin.from, origin.capacity, -origin.cost);
			clone.flow = origin.capacity;
			clone.complement = origin;
			origin.complement = clone;
			edges.add(clone);
		}

		int[] p = new int[n];
		for(Edge e : edges)p[e.from]++;
		for(int i = 0;i < n;i++)g[i] = new Edge[p[i]];
		for(Edge e : edges)g[e.from][--p[e.from]] = e;
		return g;
	}

	// NOT VERIFIED
	public static Edge[][] compileWU(int n, List<Edge> edges)
	{
		Edge[][] g = new Edge[n][];
		// cloning
		for(int i = edges.size()-1;i >= 0;i--){
			Edge origin = edges.get(i);
			Edge back = new Edge(origin.to, origin.from, origin.capacity, origin.cost);
			edges.add(back);
		}
		for(int i = edges.size()-1;i >= 0;i--){
			Edge origin = edges.get(i);
			Edge clone = new Edge(origin.to, origin.from, origin.capacity, -origin.cost);
			clone.flow = origin.capacity;
			clone.complement = origin;
			origin.complement = clone;
			edges.add(clone);
		}

		int[] p = new int[n];
		for(Edge e : edges)p[e.from]++;
		for(int i = 0;i < n;i++)g[i] = new Edge[p[i]];
		for(Edge e : edges)g[e.from][--p[e.from]] = e;
		return g;
	}

	public static class DQ {
		public int[] q;
		public int n;
		protected int pt, ph;

		public DQ(int n){ this.n = Integer.highestOneBit(n)<<1; q = new int[this.n]; pt = ph = 0; }

		public void addLast(int x){ q[ph] = x; ph = ph+1&n-1; }
		public void addFirst(int x){ pt = pt+n-1&n-1; q[pt] = x; }
		public int pollFirst(){ int ret = q[pt]; pt = pt+1&n-1; return ret; }
		public int pollLast(){ ph = ph+n-1&n-1; int ret = q[ph]; return ret; }
		public int getFirst(){ return q[pt]; }
		public int getFirst(int k){ return q[pt+k&n-1]; }
		public int getLast(){ return q[ph+n-1&n-1]; }
		public int getLast(int k){ return q[ph+n-k-1&n-1]; }
		public void clear(){ pt = ph = 0; }
		public int size(){ return ph-pt+n&n-1; }
		public boolean isEmpty(){ return ph==pt; }
	}

	public static long solveMinCostFlowWithSPFA(Edge[][] g, int source, int sink, long all)
	{
		int n = g.length;
		long mincost = 0;

		final int[] d = new int[n];
		DQ q = new DQ(n);
		boolean[] inq = new boolean[n];
		while(all > 0){
			// shortest path src->sink
			Edge[] inedge = new Edge[n];
			Arrays.fill(d, Integer.MAX_VALUE / 2);
			d[source] = 0;
			q.addLast(source);
			while(!q.isEmpty()){
				int cur = q.pollFirst();
				inq[cur] = false;
				for(Edge ne : g[cur]){
					if(ne.capacity - ne.flow > 0){
						int nd = d[cur] + ne.cost;
						if(d[ne.to] > nd){
							inedge[ne.to] = ne;
							d[ne.to] = nd;
							if(!inq[ne.to]){
								q.addLast(ne.to);
								inq[ne.to] = true;
							}
						}
					}
				}
			}

			if(inedge[sink] == null)break;

			long minflow = all;
			long sumcost = 0;
			for(Edge e = inedge[sink];e != null;e = inedge[e.from]){
				if(e.capacity - e.flow < minflow)minflow = e.capacity - e.flow;
				sumcost += e.cost;
			}
			mincost += minflow * sumcost;
			for(Edge e = inedge[sink];e != null;e = inedge[e.from]){
				e.flow += minflow;
				e.complement.flow -= minflow;
			}

			all -= minflow;
		}
		return mincost;
	}

	static int[][] packU(int n, int[] from, int[] to) {
		int[][] g = new int[n][];
		int[] p = new int[n];
		for (int f : from)
			p[f]++;
		for (int t : to)
			p[t]++;
		for (int i = 0; i < n; i++)
			g[i] = new int[p[i]];
		for (int i = 0; i < from.length; i++) {
			g[from[i]][--p[from[i]]] = to[i];
			g[to[i]][--p[to[i]]] = from[i];
		}
		return g;
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new G().run(); }

	private byte[] inbuf = new byte[1024];
	public int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}