// Arup Guha
// 4/25/2017
// Solution to 2017 NAIPC Problem E: Blazing New Trails
// I got this idea from our programming team, who got it from Matt, after the contest.

import java.io.*;
import java.util.*;

public class newtrails {

	public static int n;
	public static ArrayList<edge> graph;
	public static ArrayList<edge> magicList;
	public static boolean[] magic;
	public static int target;

	public static void main(String[] args) throws Exception {

		BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer tok = new StringTokenizer(stdin.readLine());

		// Get main problem info.
		n = Integer.parseInt(tok.nextToken());
		int e = Integer.parseInt(tok.nextToken());
		int numMagic = Integer.parseInt(tok.nextToken());
		target = Integer.parseInt(tok.nextToken());

		// Read in special vertices.
		magic = new boolean[n];
		for (int i=0; i<numMagic; i++)
			magic[Integer.parseInt(stdin.readLine().trim())-1] = true;

		// Now store graph.
		graph = new ArrayList<edge>();
		magicList = new ArrayList<edge>();
		for (int i=0; i<e; i++) {
			tok = new StringTokenizer(stdin.readLine());
			int v1 = Integer.parseInt(tok.nextToken())-1;
			int v2 = Integer.parseInt(tok.nextToken())-1;
			int w = Integer.parseInt(tok.nextToken());
			boolean isMagic = xor(magic[v1], magic[v2]);
			edge e1 = new edge(v1, v2, w, isMagic);
			graph.add(e1);
			if (isMagic) magicList.add(e1);
		}

		// Ta da!
		System.out.println(solve());
	}

	// Adds offset to each magic edge.
	public static void addMagic(int offset) {
		for (edge e: magicList)
			e.w += offset;
	}

	public static long solve() {

		long[] res1 = mst(false);
		long[] res2 = mst(true);

		// When input graph has no mst.
		if (res1 == null || res2 == null) return -1;

		// The regular MST is valid, so return it.
		if (res2[1] <= target && target <= res1[1])
			return res1[0];

		// If we try not to take these edges and we still get too many, then it's impossible.
		addMagic(100000);
		long[] tmp = mst(true);
		if (tmp[1] > target) return -1;

		// Now, make these smaller than everyone. If we don't get enough, it's impossible.
		addMagic(-200000);
		tmp = mst(false);
		if (tmp[1] < target) return -1;

		// Now back to original graph.
		addMagic(100000);

		// Here is our binary search.
		int low = -100000, high = 100000;
		while (low <= high) {

			int mid = (low+high)/2;
			addMagic(mid);
			res1 = mst(false);
			res2 = mst(true);

			// Can return result here!
			if (res2[1] <= target && target <= res1[1]) {
				return res2[0] - ((long)target)*mid;
			}

			// Update high or low.
			if (res2[1] < target && res1[1] < target) high = mid-1;
			if (res2[1] > target && res1[1] > target) low = mid+1;

			// Undo
			addMagic(-mid);
		}

		// It should probably never get here.
		res2 = mst(true);
		return res2[0] - ((long)target)*low;
	}

	// Returns the MST and # of Magic Edges given that we either take magic edges first on ties (if magicLast is false)
	// or last on ties (magicLast is true).
	public static long[] mst(boolean magicLast) {

		long res = 0;
		long numMagic = 0;
		int numE = 0;

		// Set up appropriate sort.
		if (!magicLast)
		 	Collections.sort(graph);
		 else
		 	Collections.sort(graph, edge.MagicLastComparator);

		dset dj = new dset(n);

		// Loop till tree is complete.
		int i = 0;
		while (i < graph.size() && numE < n-1) {

			edge cur = graph.get(i);

			// In same tree.
			if (dj.find(cur.v1) == dj.find(cur.v2)) {
				i++;
				continue;
			}

			// Add edge to mst.
			dj.union(cur.v1, cur.v2);
			res += cur.w;
			numE++;
			if (xor(magic[cur.v1], magic[cur.v2])) numMagic++;
			i++;
		}

		// Not a connected graph...
		if (numE < n-1) return null;

		// If we get here, we got an MST.
		return new long[]{res, numMagic};
	}

	public static boolean xor(boolean a, boolean b) {
		return (a && !b) || (!a && b);
	}
}

//  Just used for the Disjoint set class.
class pair {
	public int parent;
	public int height;

	public pair(int a, int b) {
		parent = a;
		height = b;
	}
}

// Basic Disjoint Set without path compression.
class dset {

	private pair[] parents;

	public dset(int n) {
		parents = new pair[n];
		for (int i=0; i<n; i++)
			parents[i] = new pair(i,0);
	}

	public int find(int child) {
		while (parents[child].parent != child)
			child = parents[child].parent;
		return child;
	}

	public boolean union(int c1, int c2) {
		int root1 = find(c1);
		int root2 = find(c2);

		// Nothing to union.
		if (root1 == root2)
			return false;

		// Root 1 stays parent.
		if (parents[root1].height > parents[root2].height) {
			parents[root2].parent = root1;
		}

		// Tie case get assigned to root 1 also.
		else if (parents[root1].height == parents[root2].height) {
			parents[root2].parent = root1;
			parents[root1].height++;
		}

		// Must use root 2 here.
		else {
			parents[root1].parent = root2;
		}

		return true;
	}
}

class edge implements Comparable<edge> {

	public int v1;
	public int v2;
	public int w;
	public boolean magic;

	public edge(int myv1, int myv2, int myw, boolean isMagic) {
		v1 = myv1;
		v2 = myv2;
		w = myw;
		magic = isMagic;
	}

	// Special edges come first here.
	public int compareTo(edge other) {
		if (this.w != other.w)
			return this.w - other.w;
		if (this.magic && !other.magic) return -1;
		if (!this.magic && other.magic) return 1;
		return 0;
	}

	// Here, magic edges come last.
	public static Comparator<edge> MagicLastComparator
                          = new Comparator<edge>() {

	    public int compare(edge a, edge b) {
			if (a.w != b.w)return a.w - b.w;
			if (a.magic && !b.magic) return 1;
			if (!a.magic && b.magic) return -1;
			return 0;
	    }
	};
}