思路:
先将所有边求出来,有负边权spfa求最短路即可,图中可能有负环,当存在负环时所有可达点都变成了负无穷,但是这样写确过不了,改成遇到负环就return但是前面求的最短路不变成负无穷就过了
代码:
#include <iostream>
#include <algorithm>
#include <iostream>
#include <string>
#include <stdio.h>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <math.h>
#include <climits>
#include <iomanip>
#include <queue>
#include <vector>
#define fastio ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL)
#define debug(a) cout << "debug : " << (#a) << " = " << a << endl
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int N = 210;
const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
const int mod = 998244353;
int n, m;
vector<PII> a[N];
int w[N], dis[N], cnt[N];
bool vis[N], flag;
void spfa()
{
for (int i = 1; i <= n; i++)
dis[i] = INF;
// debug(dis[4]);
memset(vis, false, sizeof vis);
memset(cnt, 0, sizeof cnt);
queue<int> q;
dis[1] = 0, cnt[1] = 1;
q.push(1);
vis[1] = true;
while (q.size())
{
int t = q.front();
q.pop();
vis[t] = false;
for (auto p : a[t])
{
int j = p.second, w = p.first;
if (dis[j] > w + dis[t])
{
dis[j] = w + dis[t];
cnt[j] = cnt[t] + 1;
if (cnt[j] > n)
{
flag = true;
return;
}
if (!vis[j])
{
q.push(j);
vis[j] = true;
}
}
}
}
}
int main()
{
// fastio;
int T;
cin >> T;
for (int j = 1; j <= T; j++)
{
flag = false;
scanf("%d", &n);
for (int i = 1; i <= n; i++)
a[i].clear();
for (int i = 1; i <= n; i++)
scanf("%d", &w[i]);
scanf("%d", &m);
while (m--)
{
int l, r;
scanf("%d%d", &l, &r);
int t = w[r] - w[l];
a[l].push_back({t * t * t, r});
}
spfa();
int q;
scanf("%d", &q);
printf("Case %d:\n", j);
while (q--)
{
int x;
cin >> x;
if (dis[x] < 3 || dis[x] == INF)
printf("?\n");
else
printf("%d\n", dis[x]);
}
}
return 0;
}