题意:收过路费.如果最后的收费小于3或不能达到,输出'?'.否则输出到n点最小的过路费
分析:关键权值可为负,如果碰到负环是,小于3的约束条件不够,那么在得知有负环时,把这个环的点都标记下,DFS实现.
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> using namespace std; const int N = 2e2 + 5; const int E = 1e4 + 5; const int INF = 0x3f3f3f3f; struct Edge { int v, w, nex; Edge() {} Edge(int v, int w, int nex) : v (v), w (w), nex (nex) {} bool operator < (const Edge &r) const { return w > r.w; } }edge[E]; int head[N]; int d[N]; int cnt[N]; int a[N]; bool vis[N], vis2[N]; int n, m, e; void init() { memset (head, -1, sizeof (head)); e = 0; } void add_edge(int u, int v, int w) { edge[e] = Edge (v, w, head[u]); head[u] = e++; } void DFS(int u) { vis2[u] = true; for (int i=head[u]; ~i; i=edge[i].nex) { int v = edge[i].v; if (!vis2[v]) { DFS (v); } } } void SPFA(int s) { memset (cnt, 0, sizeof (cnt)); memset (vis, false, sizeof (vis)); memset (vis2, false, sizeof (vis2)); memset (d, INF, sizeof (d)); d[s] = 0; cnt[s] = 0; vis[s] = true; queue<int> que; que.push (s); while (!que.empty ()) { int u = que.front (); que.pop (); vis[u] = false; for (int i=head[u]; ~i; i=edge[i].nex) { int v = edge[i].v, w = edge[i].w; if (vis2[v]) continue; if (d[v] > d[u] + w) { d[v] = d[u] + w; if (!vis[v]) { vis[v] = true; que.push (v); if (++cnt[v] > n) { DFS (v); } } } } } } int cal(int i, int j) { int ret = a[i] - a[j]; ret = ret * ret * ret; return ret; } int main(void) { int T, cas = 0; scanf ("%d", &T); while (T--) { init (); scanf ("%d", &n); for (int i=1; i<=n; ++i) { scanf ("%d", &a[i]); } scanf ("%d", &m); for (int u, v, i=1; i<=m; ++i) { scanf ("%d%d", &u, &v); add_edge (u, v, cal (v, u)); } SPFA (1); int q; scanf ("%d", &q); printf ("Case %d: ", ++cas); while (q--) { int x; scanf ("%d", &x); if (d[x] == INF || d[x] < 3 || vis2[x]) puts ("?"); else printf ("%d ", d[x]); } } return 0; }