每个junction就是图的一个顶点,边权就是(终点的busyness-起点的busyness) ,所以可能会出现负边和负环。要用Bellman-Ford算法求单源最短路。
在这里要注意,本题的图中是包含负环的,对于能求得最短路的点就求,不能到达的点和无最短路的点都要标记出来。
d[i]==inf 表示i处无法到达,d[i]仍是初始值;cnt[i]>=n,代表i点已经n次入栈,如果有最短路,至多n-1次就已经求得最短路,所以这种点就是无最短路的,在spfa时要注意每个点最多入栈n次,这样避免了无限循环,并区分开了有没有最短路的点,因为对于存在最短路的点,最多入了n-1次栈就不会再入了,而不存在的就会再入一次,达到n次。
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
#define cube(x) ((x)*(x)*(x))
#define maxn 205
#define maxm 20000
#define inf 0x3f3f3f3f
using namespace std;
struct Edge
{
int v, w;
} edge[maxm];
int n, b[maxn], m, d[maxn],cnt[maxn];
int head[maxn], nxt[maxm];
bool ins[maxn];
void spfa()
{
stack<int> s;
memset(ins + 1, 0, sizeof(bool)*n);
memset(cnt + 1, 0, sizeof(int)*n);
memset(d + 1, 0x3f, sizeof(int)*n);
d[1] = 0;
ins[1] = true;
cnt[1] = 1;
s.push(1);
while (!s.empty())
{
int t=s.top(); s.pop();
ins[t] = false;
for (int cur = head[t]; cur != -1; cur = nxt[cur])
{
Edge& e = edge[cur];
if (d[e.v] > d[t] + e.w)
{
d[e.v] = d[t] + e.w;
if (!ins[e.v]&&cnt[e.v]<n)
{
ins[e.v] = true;
s.push(e.v);
cnt[e.v]++;
}
}
}
}
}
int main()
{
int T;
scanf("%d", &T);
for (int r = 1; r <= T; r++)
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &b[i]);
scanf("%d", &m);
memset(head + 1, -1, sizeof(int)*n);
for (int i = 0,u; i < m; i++)
{
scanf("%d%d",&u,&edge[i].v);
nxt[i] = head[u];
head[u] = i;
edge[i].w = cube(b[edge[i].v] - b[u]);
}
spfa();
printf("Case %d:\n", r);
int q, des;
scanf("%d", &q);
for (int i = 0; i < q; i++)
{
scanf("%d", &des);
if (d[des] == inf || d[des] < 3 || cnt[des]>=n) printf("?\n");
else printf("%d\n", d[des]);
}
}
return 0;
}