题目大意:给你n个顶点,和m条边,边权计算(终点-起点)的立方,然后要你求最短路,如果不存在这条路或者这条路权值<3,输出?。
思路:因为(终点-起点)的立方有可能会出现负数因此我们不但要找最短路还需要判负环,因为有负数dijkstra就用不了了,这里用spfa找负环,用dfs把负环都染色。
代码:

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=205;
int cnt;
int t,n,m;
typedef struct {
	int nxt,to,w;
}edge;
int head[maxn],num[maxn],dis[maxn],cir[maxn];
edge edges[maxn*100];
int v[maxn],vis[maxn];
void add(int from,int to,int w){
	edges[++cnt].to=to;
	edges[cnt].w=w;
	edges[cnt].nxt=head[from];
	head[from]=cnt;
}
void dfs(int id){
	cir[id]=true;
	for(int i=head[id];i;i=edges[i].nxt){
		if(!cir[edges[i].to])
		dfs(edges[i].to);
	}
}
void spfa(int s){
	queue<int>st;
	st.push(s);
	num[1]=1;vis[1]=1;dis[1]=0;
	while(!st.empty()){
		int cur=st.front();st.pop();
		vis[cur]=false;
		if(cir[cur])continue;
		for(int i=head[cur];i;i=edges[i].nxt){
			int v=edges[i].to;
			if(dis[v]>edges[i].w+dis[cur]){
				dis[v]=edges[i].w+dis[cur];
				if(!vis[v]){
					st.push(v);
					vis[v]=true;
					num[v]++;
					if(num[v]==n){
						dfs(v);
					}
				}
			}
		}
	}
} 
void init(){
	memset(dis,88,sizeof(dis));
	memset(head,0,sizeof(head));
	memset(num,0,sizeof(num));
	memset(vis,0,sizeof(vis));
	memset(cir,0,sizeof(cir));
	cnt=0;
}
int main(){
	cin>>t;
	int x,y;
	int qt=1;
	while(t--){
		init();
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>v[i];
		}
		cin>>m;
		for(int i=1;i<=m;i++){
			cin>>x>>y;
			add(x,y,((v[y]-v[x])*(v[y]-v[x])*(v[y]-v[x])));
		}
		spfa(1);
		cout<<"Case "<<qt++<<":"<<endl;
		int ca,query;
		cin>>ca;
		for(int i=1;i<=ca;i++){
			cin>>query;
			if(dis[query]>=inf||dis[query]<3||cir[query]){
				cout<<"?"<<endl;
			}else{
				cout<<dis[query]<<endl;
			}
		}
	}
}