using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("4 1");
WillReturn.Add("1 2 10");
WillReturn.Add("2 100");
WillReturn.Add("1 3");
WillReturn.Add("5");
WillReturn.Add("3");
WillReturn.Add("1 2 3 60");
WillReturn.Add("3");
WillReturn.Add("2 4");
WillReturn.Add("3");
//440
//280
//900
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static long[] GetSplitArr(string pStr)
{
return (pStr == "" ? new string[0] : pStr.Split(' ')).Select(pX => long.Parse(pX)).ToArray();
}
static void Main()
{
List<string> InputList = GetInputList();
long[] wkArr = { };
Action<string> SplitAct = (pStr) => wkArr = GetSplitArr(pStr);
SplitAct(InputList[0]);
long NodeCnt = wkArr[0];
long M = wkArr[1];
SplitAct(InputList[(int)M + 1]);
long DCnt = wkArr[0];
long T = wkArr[1];
long[] DArr = GetSplitArr(InputList[(int)M + 2]);
long AirNode = NodeCnt + 1;
long UB = AirNode;
long[,] KyoriArr = new long[UB + 1, UB + 1];
const long INFTY = long.MaxValue;
// 初期化処理
for (long I = 0; I <= UB; I++) {
for (long J = 0; J <= UB; J++) {
KyoriArr[I, J] = (I == J) ? 0 : INFTY;
}
}
foreach (string EachStr in InputList.Skip(1).Take((int)M)) {
SplitAct(EachStr);
long FromNode = wkArr[0];
long ToNode = wkArr[1];
long Cost = wkArr[2];
Cost *= 2;
KyoriArr[FromNode, ToNode] = Math.Min(KyoriArr[FromNode, ToNode], Cost);
KyoriArr[ToNode, FromNode] = Math.Min(KyoriArr[ToNode, FromNode], Cost);
}
foreach (long EachD in DArr) {
KyoriArr[EachD, AirNode] = T;
KyoriArr[AirNode, EachD] = T;
}
// ワーシャルフロイド法
for (long K = 0; K <= UB; K++) {
for (long I = 0; I <= UB; I++) {
if (KyoriArr[I, K] == INFTY) continue;
for (long J = 0; J <= UB; J++) {
if (KyoriArr[K, J] == INFTY) continue;
long CurrKouho = KyoriArr[I, K] + KyoriArr[K, J];
if (KyoriArr[I, J] > CurrKouho) {
KyoriArr[I, J] = CurrKouho;
}
}
}
}
// ワーシャルフロイド法の結果の部分更新
Action<List<long>> ExecPartUpdate = (pKList) =>
{
foreach (long K in pKList) {
for (long I = 0; I <= UB; I++) {
if (KyoriArr[I, K] == INFTY) continue;
for (long J = 0; J <= UB; J++) {
if (KyoriArr[K, J] == INFTY) continue;
long CurrKouho = KyoriArr[I, K] + KyoriArr[K, J];
if (KyoriArr[I, J] > CurrKouho) {
KyoriArr[I, J] = CurrKouho;
}
}
}
}
};
foreach (string EachStr in InputList.Skip(1 + (int)M + 3)) {
SplitAct(EachStr);
long Type = wkArr[0];
if (Type == 1) {
long FromNode = wkArr[1];
long ToNode = wkArr[2];
long Cost = wkArr[3];
Cost *= 2;
KyoriArr[FromNode, ToNode] = Math.Min(KyoriArr[FromNode, ToNode], Cost);
KyoriArr[ToNode, FromNode] = Math.Min(KyoriArr[ToNode, FromNode], Cost);
var KList = new List<long>();
KList.Add(FromNode);
KList.Add(ToNode);
ExecPartUpdate(KList);
}
if (Type == 2) {
long X = wkArr[1];
KyoriArr[X, AirNode] = T;
KyoriArr[AirNode, X] = T;
var KList = new List<long>();
KList.Add(X);
KList.Add(AirNode);
ExecPartUpdate(KList);
}
if (Type == 3) {
long Answer = 0;
for (long I = 1; I <= NodeCnt; I++) {
for (long J = 1; J <= NodeCnt; J++) {
if (KyoriArr[I, J] == INFTY) continue;
Answer += KyoriArr[I, J];
}
}
Console.WriteLine(Answer / 2);
}
}
}
}