题目大意:给出每个点的权值和边,假设边为(u, v),那么该边的权值就是(val[v] - val[u]) ^ 3
问从点1出发,到达所给点的最短路
解题思路:有可能会出现负环,出现负环的话,就将负环内的点所能到达的所有点都标记一下
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N = 210;
const int M = 100010;
const int INF = 0x3f3f3f3f;
struct Edge{
int u, v, dis, next;
Edge() {}
Edge(int u, int v, int dis, int next): u(u), v(v), dis(dis), next(next) {}
}E[M * 2];
int val[N], head[N] ,cnt[N], d[N];
bool vis[N], cycle[N];
int n, m, cas = 1;
void dfs(int u) {
cycle[u] = true;
for (int i = head[u]; ~i; i = E[i].next){
int v = E[i].v;
if (cycle[v]) continue;
dfs(v);
}
}
void solve() {
queue<int> Q;
for (int i = 1; i <= n; i++) d[i] = INF;
d[1] = 0;
memset(vis, 0, sizeof(vis));
memset(cnt, 0, sizeof(cnt));
memset(cycle, 0, sizeof(cycle));
Q.push(1);
while (!Q.empty()) {
int u = Q.front(); Q.pop();
vis[u] = false;
for (int i = head[u]; ~i; i = E[i].next) {
int v = E[i].v;
if (cycle[v]) continue;
if (d[v] > d[u] + E[i].dis) {
d[v] = d[u] + E[i].dis;
if (!vis[v]) {
vis[v] = true;
Q.push(v);
if (++cnt[v] >= n) {
dfs(v);
}
}
}
}
}
int q, u;
printf("Case %d:\n", cas++);
scanf("%d", &q);
while (q--) {
scanf("%d", &u);
if (cycle[u] || d[u] < 3 || d[u] == INF) printf("?\n");
else printf("%d\n", d[u]);
}
}
int getdis(int t) {
return t * t * t;
}
void init() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &val[i]);
memset(head, -1, sizeof(head));
scanf("%d", &m);
int u, v;
for (int i = 0; i < m; i++) {
scanf("%d%d", &u, &v);
E[i] = Edge(u, v, getdis(val[v] - val[u]), head[u]);
head[u] = i;
}
}
int main() {
int test;
scanf("%d", &test);
while (test--) {
init();
solve();
}
return 0;
}