#include<iostream>
#include<cstring>
#include<stdio.h>
#include<queue>
using namespace std;
const int maxn = 100010;
const int INF = 0x3f3f3f3f;
int dis[maxn],head[maxn],vis[maxn],cir[maxn],a[maxn],num[maxn],n,m,cnt,k,q;
//cir[i]表示i点是否在负环上,num[i]表示i点的入队列次数
struct edge
{
int v;
int w;
int next;
} e[maxn];
void add(int u,int v,int w)
{
e[cnt].v = v;
e[cnt].w = w*w*w;
e[cnt].next = head[u];
head[u] = cnt++;
}
void dfs(int u)//u点已经入队大于n次,所以u点在负环上,与他相连的点也在负环上
{
cir[u] = 1;
for(int i = head[u]; i != -1; i = e[i].next)
{
int v = e[i].v;
if(!cir[v])
dfs(v);
}
}
void Init()
{
cnt=1;
memset(dis,INF,sizeof(dis));
memset(num,0,sizeof(num));
memset(cir,0,sizeof(cir));
memset(vis,0,sizeof(vis));
memset(head,-1,sizeof(head));
}
void SPFA()
{
queue<int>que;
que.push(1);
vis[1] = 1;
dis[1] = 0;
num[1] = 1;
while(!que.empty())
{
int u =que.front();
que.pop();
vis[u] = 0;
for(int i = head[u]; i != -1; i = e[i].next)
{
int v = e[i].v,w = e[i].w;
if(cir[v])
continue;//如果已经在负环上就不算
if(dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
if(!vis[v])
{
que.push(v);
vis[v] = 1;
num[v]++;
if(num[v] > n)
dfs(v);//标记负环上的点
}
}
}
}
}
int main()
{
int t;
int cas = 0;
scanf("%d",&t);
while(t--)
{
Init();
scanf("%d",&n);
for(int i = 1; i <= n; i++)
scanf("%d",&a[i]);
scanf("%d",&m);
while(m--)
{
int u,v,w;
scanf("%d %d",&u,&v);
w = a[v]-a[u];
add(u,v,w);
}
SPFA();
printf("Case %d:\n",++cas);
scanf("%d",&k);
while(k--)
{
scanf("%d",&q);
if(cir[q] || dis[q] < 3 || dis[q] == INF)
cout<<"?"<<endl;
else
cout<<dis[q]<<endl;
}
}
return 0;
}