import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.StringTokenizer;
import java.util.Map;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Set;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.FileNotFoundException;
import java.io.File;
import java.util.List;
import java.util.TreeMap;
import java.io.Writer;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
  public static void main(String[] args) {
    InputStream inputStream = System.in;
    OutputStream outputStream = System.out;
    InputReader in = new InputReader(inputStream);
    OutputWriter out = new OutputWriter(outputStream);
    E solver = new E();
    solver.solve(1, in, out);
    out.close();
  }

  static class E extends SimpleSavingChelperSolution {
    private int[] x;
    private int[] y;
    private int n;
    private Map<Integer, Integer> xMap;
    private Map<Integer, Integer> yMap;
    private List<Set<Integer>> edges;
    private boolean[] visited;
    private long MOD;

    public void solve(int testNumber, InputReader in, OutputWriter out) {
      wrapSolve(testNumber, in, out);
    }

    public void solve(int testNumber) {
      n = in.nextInt();

      x = new int[n];
      y = new int[n];

      xMap = new TreeMap<>();
      yMap = new TreeMap<>();

      edges = new ArrayList<>();

      for (int i = 0; i < n; i++) {
        edges.add(new HashSet<>());
      }

      Map<Integer, Integer> prevX = new HashMap<>();
      Map<Integer, Integer> prevY = new HashMap<>();

      for (int i = 0; i < n; i++) {
        x[i] = in.nextInt();
        y[i] = in.nextInt();

        xMap.put(x[i], xMap.getOrDefault(x[i], 0) + 1);
        yMap.put(y[i], yMap.getOrDefault(y[i], 0) + 1);

        Integer pX = prevX.get(x[i]);
        Integer pY = prevY.get(y[i]);

        if (pX != null) {
          edges.get(pX).add(i);
          edges.get(i).add(pX);
        }
        if (pY != null) {
          edges.get(pY).add(i);
          edges.get(i).add(pY);
        }

        prevX.put(x[i], i);
        prevY.put(y[i], i);
      }

      visited = new boolean[n];

      long ans = 1;

      MOD = 1000000007;

      for (int i = 0; i < n; i++) {
        if (visited[i]) {
          continue;
        }

        List<Integer> res = new ArrayList<>();
        dfs(i, res);

        Set<Integer> usedX = new HashSet<>();
        Set<Integer> usedY = new HashSet<>();

        for (Integer j : res) {
          usedX.add(x[j]);
          usedY.add(y[j]);
        }

        int K = usedX.size() + usedY.size();
        if (res.size() >= K) {
          ans = ans * twopow(K) % MOD;
        } else {
          ans = ans * ((twopow(K) - 1 + MOD) % MOD) % MOD;
        }
      }

      out.println(ans);
    }

    long twopow(int n) {
      if (n == 0) {
        return 1;
      }
      if (n % 2 == 0) {
        long t = twopow(n / 2);
        return t * t % MOD;
      }
      return twopow(n - 1) * 2 % MOD;
    }

    void dfs(int v, List<Integer> res) {
      if (visited[v]) {
        return;
      }
      visited[v] = true;
      res.add(v);

      for (int j : edges.get(v)) {
        dfs(j, res);
      }
    }

  }

  static class InputReader {
    private BufferedReader br;
    private StringTokenizer in;

    public InputReader(String fileName) {
      try {
        br = new BufferedReader(new FileReader(fileName));
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }

    public InputReader(InputStream inputStream) {
      br = new BufferedReader(new InputStreamReader(inputStream));
    }

    private boolean hasMoreTokens() {
      while (in == null || !in.hasMoreTokens()) {
        String s = nextLine();
        if (s == null) {
          return false;
        }
        in = new StringTokenizer(s);
      }
      return true;
    }

    public String nextString() {
      return hasMoreTokens() ? in.nextToken() : null;
    }

    public String nextLine() {
      try {
        in = null;
        return br.readLine();
      } catch (Exception e) {
        e.printStackTrace();
        return null;
      }
    }

    public int nextInt() {
      return Integer.parseInt(nextString());
    }

  }

  static class OutputWriter extends PrintWriter {

    public void close() {
      super.close();
    }

    public OutputWriter(String fileName) throws FileNotFoundException {
      super(fileName);
    }

    public OutputWriter(OutputStream outputStream) {
      super(outputStream);
    }

    public OutputWriter(Writer writer) {
      super(writer);
    }

  }

  static abstract class SimpleSavingChelperSolution extends SavingChelperSolution {

    public String processOutputPreCheck(int testNumber, String output) {
      return output;
    }

    public String processOutputPostCheck(int testNumber, String output) {
      return output;
    }

  }

  static abstract class SavingChelperSolution {
    protected int testNumber;
    public InputReader in;
    public OutputWriter out;
    private OutputWriter toFile;
    private boolean local = new File("chelper.properties").exists();
    public OutputWriter debug;

    {
      if (local) {
        debug = new OutputWriter(System.out);
      } else {
        debug = new OutputWriter(new OutputStream() {

          public void write(int b) {
          }
        });
      }
    }

    public SavingChelperSolution() {
      try {
        toFile = new OutputWriter("last_test_output.txt");
      } catch (FileNotFoundException e) {
        throw new RuntimeException(e);
      }
    }

    public abstract void solve(int testNumber);

    public abstract String processOutputPreCheck(int testNumber, String output);

    public abstract String processOutputPostCheck(int testNumber, String output);

    public void wrapSolve(int testNumber, InputReader in, OutputWriter out) {
      this.testNumber = testNumber;

      ByteArrayOutputStream substituteOutContents = new ByteArrayOutputStream();
      OutputWriter substituteOut = new OutputWriter(substituteOutContents);

      this.in = in;
      this.out = substituteOut;

      solve(testNumber);
      substituteOut.flush();

      String result = substituteOutContents.toString();

      result = processOutputPreCheck(testNumber, result);
      out.print(result);
      out.flush();

      if (local) {
        debug.flush();

        result = processOutputPostCheck(testNumber, result);
        toFile.print(result);
        toFile.flush();
      }
    }

  }
}


import java.io.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.StringTokenizer;

public class Main {

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

        Scanner sc = new Scanner(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int n = sc.nextInt();
        HashSet<Integer> x = new HashSet<>(), y = new HashSet<>();
        HashMap<Integer, Integer> mapX = new HashMap<>(), mapY = new HashMap<>();
        int[][] arr = new int[2][n];
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < 2; j++) {
                arr[j][i] = sc.nextInt();
                if (j == 0) x.add(arr[j][i]);
                else y.add(arr[j][i]);
            }
        }

        int mapIdxX = 0;
        for (int xx : x) if (!mapX.containsKey(xx)) mapX.put(xx, mapIdxX++);
        for (int yy : y) if (!mapY.containsKey(yy)) mapY.put(yy, mapIdxX++);

        UnionFind uf = new UnionFind(mapIdxX);
        for (int i = 0; i < n; i++)
            uf.unionSet(mapX.get(arr[0][i]), mapY.get(arr[1][i]));

        uf.close();
        long res = 1;
        int mod = (int) 1e9 + 7;
        factorial();
        for (int i = 0; i < mapIdxX; i++)
            if (uf.p[i] == i) {
                int numPoints = uf.numPoints[i], lines = uf.sizeOfSet(i);
                long ways = 0;
                for (int j = 0; j <= Math.min(numPoints, lines); j++) {
                    ways += ncr(lines, j);
                    if (ways >= mod) ways -= mod;
                }
                res *= ways;
                res %= mod;

            }

        out.println(res);
        out.close();
    }

    // O(1) nCr
    static int MAX = 5 * 100000 + 1;
    static int fact[] = new int[MAX];
    static int MOD = (int) 1e9 + 7;

    static int ncr(int n, int r) {
        return (int) ((long) fact[n] * ((inv(fact[r], MOD) * inv(fact[n - r], MOD)) % MOD) % MOD) % MOD;
    }

    static long inv(long x, long mod) {
        long r, y;
        for (r = 1, y = mod - 2; y != 0; x = x * x % mod, y >>= 1)
            if ((y & 1) == 1)
                r = r * x % mod;
        return r;
    }

    static void factorial() {
        fact[0] = fact[1] = 1;
        for (int i = 2; i < MAX; i++)
            fact[i] = (int) ((long) i * fact[i - 1] % MOD);
    }

    public static long modular_exponentiation(long a, long b, long c) // returns ( a ^ b ) % c
    {
        long ans = 1L;
        while (b != 0) {
            if ((b & (1)) == 1)
                ans = (ans * a) % c;

            a = (a * a) % c;
            b >>= 1L;
        }

        return ans;
    }

    static class UnionFind {
        private int[] p, rank, setSize, numPoints;
        private int numSets;

        public UnionFind(int size) {
            p = new int[size];
            rank = new int[size];
            setSize = new int[size];
            numPoints = new int[size];
            numSets = size;
            for (int i = 0; i < size; ++i) {
                p[i] = i;
                numPoints[i] = 0;
                setSize[i] = 1;
            }
        }

        int findSet(int i) {
            return (p[i] == i) ? i : (p[i] = findSet(p[i]));
        }

        boolean isSameSet(int i, int j) {
            return findSet(i) == findSet(j);
        }

        void unionSet(int i, int j) {
            if (!isSameSet(i, j)) {
                --numSets;
                int x = findSet(i), y = findSet(j);
                if (rank[x] > rank[y]) {
                    p[y] = x;
                    setSize[x] = setSize[x] + setSize[y];
                    numPoints[x] = 1 + numPoints[x] + numPoints[y];
                } else {
                    p[x] = y;
                    setSize[y] = setSize[y] + setSize[x];
                    numPoints[y] = numPoints[y] + numPoints[x] + 1;
                    if (rank[x] == rank[y]) ++rank[y];
                }
            } else {
                numPoints[findSet(i)]++;
            }
        }

        int numDisjointSets() {
            return numSets;
        }

        void close() {
            for (int i = 0; i < p.length; i++)
                findSet(i);
        }

        int sizeOfSet(int i) {
            return setSize[findSet(i)];
        }
    }

    static class Scanner {
        StringTokenizer st;
        BufferedReader br;

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

        public Scanner(String s) throws FileNotFoundException {
            br = new BufferedReader(new FileReader(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();
        }
    }
}


import java.io.* ;
import java.util.* ;
import java.util.stream.* ;
import java.text.* ;
import java.math.* ;
public class Codeshefcode{
	public static void main(String[] args) throws IOException{
		Solver Machine = new Solver() ;
		Machine.Solve() ;
		Machine.Finish();
	}
}
class Mod{
	static long mod=1000000007 ;
	static long d(long a,long b){ return (a*MI(b))%mod ; }
	static long m(long a , long b){ return (a*b)%mod ; }
	static private long MI(long a ){ return pow(a,mod-2) ; }
	static long pow(long a,long b){
		if(b<0) return pow(MI(a),-b) ;
		long val=a ; long ans=1 ;
		while(b!=0){
			if((b&1)==1) ans = (ans*val)%mod ;
			val = (val*val)%mod ;
			b>>=1 ;
		}
		return ans ;
	}
}
class pair implements Comparable<pair>{
	long x ; int y ;
	pair(long x,int y){ this.x=x ; this.y=y ;}
	public int compareTo(pair p){
		return (this.x<p.x ? -1 : (this.x>p.x ? 1 : (this.y<p.y ? -1 : (this.y>p.y ? 1 : 0)))) ;
	}
}
class Solver{
	FasterScanner ip = new FasterScanner(System.in) ;
	PrintWriter op = new PrintWriter(System.out) ;
	long offset = 2000000001l ;
	void Solve() throws IOException{
		int m = ip.i() ;
		long edges[][] = new long[m][] ;
		for(int i=0 ; i<m ; i++){
			long tmp[] = {ip.l(),ip.l()+offset} ;
			edges[i] = tmp ;
		}
		myset set = new myset() ;
		for(int i=0 ; i<m ; i++){
			set.add(edges[i][0]) ;
			set.add(edges[i][1]) ;
		}
		mymap map = new mymap() ;
		int n=0 ;
		for(long elem : set) map.put(elem,n++) ;
		for(int i=0 ; i<m ; i++){
			long tmp[] = {map.get(edges[i][0]),map.get(edges[i][1])} ;
			edges[i] = tmp ;
		}
		mylist adj[] = new mylist[n] ;
		for(int i=0 ; i<n ; i++) adj[i] = new mylist() ;
		for(int i=0 ; i<m ; i++){
			int x = (int) edges[i][0] ;
			int y = (int) edges[i][1] ;
			adj[x].add(y) ; adj[y].add(x) ;
		}
		int comp[] = new int[n] ;
		Arrays.fill(comp,-1) ;
		int clr=0 ;
		for(int i=0 ; i<n ; i++){
			if(comp[i]==-1){
				mystack S = new mystack() ;
				S.add(i) ;
				comp[i]=clr ;
				while(!S.isEmpty()){
					int nd = S.pop() ;
					for(int nnd : adj[nd])
						if(comp[nnd]==-1){
							S.push(nnd) ;
							comp[nnd]=clr ;
						}
				}
				clr++ ;
			}
		}
		int cntn[] = new int[clr] ;
		int cntm[] = new int[clr] ;
		for(int i=0 ; i<n ; i++) cntn[comp[i]]++ ;
		for(int i=0 ; i<m ; i++) cntm[comp[(int) edges[i][0]]]++ ;
		long res=1 ;
		for(int i=0 ; i<clr ; i++){
			if(cntm[i]>=cntn[i])
				res = Mod.m(res,Mod.pow(2,cntn[i])) ;
			else
				res = Mod.m(res,Mod.pow(2,cntn[i])+(Mod.mod-1)) ;
		}
		pln(res) ;
	}
	void p(Object o){
		op.print(o) ;
	}
	void pln(Object o){
		op.println(o) ;
	}
	void pArr(String name,Object arr,char type){
		p(name+": [") ;
		if(type=='i'){
			int arr1[] = (int[]) arr ;
			for(int i=0 ; i<arr1.length ; i++) p(arr1[i]+(i+1==arr1.length ? "" : ",")) ;
		}else if(type=='l'){
			long arr1[] = (long[]) arr ;
			for(int i=0 ; i<arr1.length ; i++) p(arr1[i]+(i+1==arr1.length ? "" : ",")) ;
		}else if(type=='b'){
			boolean arr1[] = (boolean[]) arr ;
			for(int i=0 ; i<arr1.length ; i++) p((arr1[i] ? 1 : 0)+(i+1==arr1.length ? "" : ",")) ;
		}
		pln("]") ;
	}
	void Finish(){
		op.flush();
		op.close();
	}
}
@SuppressWarnings("serial")
class mylist extends ArrayList<Integer>{
}
@SuppressWarnings("serial")
class myset extends TreeSet<Long>{

}
@SuppressWarnings("serial")
class mystack extends Stack<Integer>{
}
@SuppressWarnings("serial")
class mymap extends TreeMap<Long,Integer>{
}
class FasterScanner {
	private InputStream mIs;
	private byte[] buf = new byte[1024];
	private int curChar,numChars;
	public FasterScanner() { this(System.in); }
	public FasterScanner(InputStream is) { mIs = is;}
	public int read() {
		if (numChars == -1) throw new InputMismatchException();
		if (curChar >= numChars) {
			curChar = 0;
			try { numChars = mIs.read(buf);} catch (IOException e) { throw new InputMismatchException();}
			if (numChars <= 0) return -1;
		}
		return buf[curChar++];
	}
	public String nextLine(){
		int c = read();
		while (isSpaceChar(c)) c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		} while (!isEndOfLine(c));
		return res.toString();
	}
	public String S(){
		int c = read();
		while (isSpaceChar(c)) c = read();
		StringBuilder res = new StringBuilder();
		do {
			res.appendCodePoint(c);
			c = read();
		}while (!isSpaceChar(c));
		return res.toString();
	}
	public long l(){
		int c = read();
		while (isSpaceChar(c)) c = read();
		int sgn = 1;
		if (c == '-') { sgn = -1 ; c = read() ; }
		long res = 0;
		do{
			if (c < '0' || c > '9') throw new InputMismatchException();
			res *= 10 ; res += c - '0' ; c = read();
		}while(!isSpaceChar(c));
		return res * sgn;
	}
	public int i(){
		int c = read() ;
		while (isSpaceChar(c)) c = read();
		int sgn = 1;
		if (c == '-') { sgn = -1 ; c = read() ; }
		int res = 0;
		do{
			if (c < '0' || c > '9') throw new InputMismatchException();
		res *= 10 ; res += c - '0' ; c = read() ;
		}while(!isSpaceChar(c));
		return res * sgn;
	}
	public int[] ia(int n){
		int a[] = new int[n] ;
		for(int i=0 ; i<n ; i++) a[i] = i() ;
		return a ;
	}
	public long[] la(int n){
		long a[] = new long[n] ;
		for(int i=0 ; i<n ; i++) a[i] = l() ;
		return a ;
	}
	public boolean isSpaceChar(int c) { return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1; }
	public boolean isEndOfLine(int c) { return c == '\n' || c == '\r' || c == -1; }
}


import java.util.*;
import java.io.*;
import java.math.*;
import java.lang.*;
import java.awt.*;
import java.awt.geom.*;
import java.util.stream.*;

/**
 * @author Pradyumn
 */

public class Main implements Runnable{
	public int TC = 0;
	public static void main(String[] args) {
		new Thread(null, new Main(), ":)", 1L << 26).start();
	}
	static final int MODULO = (int)(1e9 + 7);
	@SuppressWarnings("Unchecked")
	public void solve() throws IOException {
	    int n = ni();
	    HashSet<Integer> x = new HashSet<>();
	    HashSet<Integer> y = new HashSet<>();
	    HashMap<Integer, Integer> mapX = new HashMap<>();
	    HashMap<Integer, Integer> mapY = new HashMap<>();
	    int[][] pp = new int[2][n];
	    for (int i = 0; i < n;  ++i) {
	    	for(int j = 0;j < 2; ++j) {
	    		pp[j][i] = ni();
	    		if(j == 0) x.add(pp[j][i]);
	    		else y.add(pp[j][i]);
	    	}
	    }

	    int mapIdx = 0;
	    for(int xx : x)
	    	if(!mapX.containsKey(xx))
	    		mapX.put(xx, mapIdx++);

	    for(int yy : y)
	    	if(!mapY.containsKey(yy))
	    		mapY.put(yy, mapIdx++);

	    UnionFind uf = new UnionFind(mapIdx);
	    for(int i = 0;i < n; ++i) {
	    	uf.unionSet(mapX.get(pp[0][i]), mapY.get(pp[1][i]));
	    }
	    uf.close();

	    long res = 1;
	    factorial();
	    for (int i = 0; i < mapIdx; i++)
            if (uf.p[i] == i) {
                int numPoints = uf.numPoints[i], lines = uf.sizeOfSet(i);
                long ways = 0;
                for (int j = 0; j <= Math.min(numPoints, lines); j++) {
                    ways += ncr(lines, j);
                    if (ways >= MODULO) ways -= MODULO;
                }
                res *= ways;
                res %= MODULO;

            }
	    out.println(res);
	}
	// O(1) nCr
    static int MAX = 5 * 100000 + 1;
    static int fact[] = new int[MAX];

    static int ncr(int n, int r) {
        return (int) ((long) fact[n] * ((inv(fact[r], MODULO) * inv(fact[n - r], MODULO)) % MODULO) % MODULO) % MODULO;
    }

    static long inv(long x, long mod) {
        long r, y;
        for (r = 1, y = mod - 2; y != 0; x = x * x % mod, y >>= 1)
            if ((y & 1) == 1)
                r = r * x % mod;
        return r;
    }

    static void factorial() {
        fact[0] = fact[1] = 1;
        for (int i = 2; i < MAX; i++)
            fact[i] = (int) ((long) i * fact[i - 1] % MODULO);
    }

    public static long modular_exponentiation(long a, long b, long c) // returns ( a ^ b ) % c
    {
        long ans = 1L;
        while (b != 0) {
            if ((b & (1)) == 1)
                ans = (ans * a) % c;

            a = (a * a) % c;
            b >>= 1L;
        }

        return ans;
    }
	static class UnionFind {
        private int[] p, rank, setSize, numPoints;
        private int numSets;

        public UnionFind(int size) {
            p = new int[size];
            rank = new int[size];
            setSize = new int[size];
            numPoints = new int[size];
            numSets = size;
            for (int i = 0; i < size; ++i) {
                p[i] = i;
                numPoints[i] = 0;
                setSize[i] = 1;
            }
        }

        int findSet(int i) {
            return (p[i] == i) ? i : (p[i] = findSet(p[i]));
        }

        boolean isSameSet(int i, int j) {
            return findSet(i) == findSet(j);
        }

        void unionSet(int i, int j) {
            if (!isSameSet(i, j)) {
                --numSets;
                int x = findSet(i), y = findSet(j);
                if (rank[x] > rank[y]) {
                    p[y] = x;
                    setSize[x] = setSize[x] + setSize[y];
                    numPoints[x] = 1 + numPoints[x] + numPoints[y];
                } else {
                    p[x] = y;
                    setSize[y] = setSize[y] + setSize[x];
                    numPoints[y] = numPoints[y] + numPoints[x] + 1;
                    if (rank[x] == rank[y]) ++rank[y];
                }
            } else {
                numPoints[findSet(i)]++;
            }
        }

        int numDisjointSets() {
            return numSets;
        }

        void close() {
            for (int i = 0; i < p.length; i++)
                findSet(i);
        }

        int sizeOfSet(int i) {
            return setSize[findSet(i)];
        }
    }
	BufferedReader br;
	StringTokenizer st;
	PrintWriter out;
	public void run() {
		try {
			br = new BufferedReader(new InputStreamReader(System.in),32768);
			st = null;
			out = new PrintWriter(System.out);
			if(TC == 1) {
				for(int T = ni();T > 0; --T) {
					solve();
				}
			} else {
				solve();
			}
			br.close();
			out.close();
		} catch(IOException e) {
			e.printStackTrace();
			System.exit(1);
		}
	}
	public char[] nsc( ) throws IOException {
		return ns().toCharArray();
	}
	public char[][] nm(int n, int m) throws IOException {
		char[][] map = new char[n][];
		for(int i = 0;i < n; ++i) {
			map[i] = nsc();
		}
		return map;
	}
	public String ns() throws IOException {
		while (st == null || !st.hasMoreTokens()) {
			st = new StringTokenizer(br.readLine());
		}
		return st.nextToken();
	}
	public String nextLine() throws IOException {
		return br.readLine();
	}
	public int ni() throws IOException {
		return Integer.parseInt(ns());
	}

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

	public long nl() throws IOException {
		return Long.parseLong(ns());
	}

	public long[] nal(int n) throws IOException {
		long[] a = new long[n];
		for(int i = 0;i < n; ++i) a[i] = nl();
		return a;
	}

	public double nd() throws IOException {
		return Double.parseDouble(ns());
	}
	private static boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private static 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, 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.*;
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, dd, 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_];
		dd = 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] : dd[u] != dd[v] ? dd[u] - dd[v] : u - v);
		pq.add(s);
		Integer first;
		while ((first = pq.pollFirst()) != null) {
			int u = first;
			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) {
						if (pi[v] != INF)
							pq.remove(v);
						pi[v] = p;
						dd[v] = d;
						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) {
		cost_ = Arrays.copyOf(cost, 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));
	}
}


// 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 * 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));
	}
}


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 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();
        }
    }
}


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 = 150;
        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;
        }
    }
}


// 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;
	boolean[] iq;
	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_];
		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);
	}
	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] : dd[u] != dd[v] ? dd[u] - dd[v] : u - v);
		pq.add(s); iq[s] = true;
		Integer first;
		while ((first = pq.pollFirst()) != null) {
			int u = first;
			iq[u] = false;
			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) {
						if (iq[v]) {
							pq.remove(v); iq[v] = false;
						}
						pi[v] = p;
						dd[v] = d;
						bb[v] = h_;
						pq.add(v); iq[v] = true;
					}
				}
		}
		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 (dijkstra(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 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)); }
}


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, dd, 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_];
		dd = new int[n_];
		bb = 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] : dd[u] != dd[v] ? dd[u] - dd[v] : u - v);
		pq.add(s);
		Integer first;
		while ((first = pq.pollFirst()) != null) {
			int u = first;
			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) {
						if (pi[v] != INF)
							pq.remove(v);
						pi[v] = p;
						dd[v] = d;
						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) {
		cost_ = Arrays.copyOf(cost, 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));
	}
}