题意:
这一晚,TT 做了个美梦! 在梦中,TT 的愿望成真了,他成为了喵星的统领!喵星上有 N 个商业城市,编号 1 ~ N,其中 1 号城市是 TT 所在的城市,即首都。 喵星上共有 M 条有向道路供商业城市相互往来。但是随着喵星商业的日渐繁荣,有些道路变得非常拥挤。正在 TT 为之苦恼之时,他的魔法小猫咪提出了一个解决方案!TT 欣然接受并针对该方案颁布了一项新的政策。 具体政策如下:对每一个商业城市标记一个正整数,表示其繁荣程度,当每一只喵沿道路从一个商业城市走到另一个商业城市时,TT 都会收取它们(目的地繁荣程度 - 出发地繁荣程度)^ 3 的税。 TT 打算测试一下这项政策是否合理,因此他想知道从首都出发,走到其他城市至少要交多少的税,如果总金额小于 3 或者无法到达请悄咪咪地打出 '?'
AC代码:
#include <cstdio>
#include <cstring>
#include <queue>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
const int N = 205, M = 4e5 + 5, INF = 0x3f3f3f3f;
int t, n, m, k, u, v, w, len, p[N], h[N], d[N], cnt[N];//p[i] 记录每个点的权值
bool vis[N];
struct E {
int v, w, next;
} e[M];
void add(int u, int v, int w) {
e[len].v = v;
e[len].w = w;
e[len].next = h[u];
h[u] = len++;
}
bool spfa() {
memset(d, 0x3f, sizeof(d));
memset(cnt, 0, sizeof(cnt));
memset(vis, false, sizeof(vis));
d[1] = 0;
queue<int> q;
q.push(1);
while (!q.empty()) {
int u = q.front();
q.pop();
vis[u] = false;
for (int j = h[u]; j; j = e[j].next) {
int v = e[j].v;
int w = e[j].w + d[u];
if (d[v] > w) {
d[v] = w;
cnt[v] = cnt[u] + 1;
if (cnt[v] >= n) return true;
if (!vis[v]) vis[v] = true, q.push(v);
}
}
}
return false;
}
int main() {
int cas = 0;
scanf("%d", &t);
while (t--) {
memset(h, 0, sizeof(h)); len = 1;
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &p[i]);
scanf("%d", &m);
while (m--) {
scanf("%d%d", &u, &v);
w = p[v] - p[u]; //目的地-源点
add(u, v, w*w*w);
}
spfa();
printf("Case %d:\n", ++cas);
scanf("%d", &k);
while (k--) {
scanf("%d", &u);
// 小于3(可能由于负环导致) || 无解
if (d[u] < 3 || d[u] > INF / 2) printf("?\n");
else printf("%d\n", d[u]);
}
}
return 0;
}