题目大意:给你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;
}
}
}
}