题目链接:http://lightoj.com/volume_showproblem.php?problem=1074
题意:有n个城市,每个城市有一个拥堵值a[i],m条单向路u到v,从u到v所需时间是(a[v]-a[u])^3, q个查找,查找从起点1到点u的最短时间是多少;如果不能到达或者时间少于3输出-1;
可能存在负环,所以用spfa最合适。负环上的点是不能到达的,所以要注意;
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <queue> #include <stack> #include <algorithm> #include <map> #include <string> typedef long long LL; #define INF 0x3f3f3f3f #define met(a, b) memset(a, b, sizeof(a)) #define N 515 using namespace std; int G[N][N], cnt[N], n, vis[N], dist[N], a[N], flag; void Init() { flag = 0; for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) G[i][j] = INF; G[i][i] = vis[i] = cnt[i] = 0; dist[i] = INF; } } void SPFA() { cnt[1] = 1; dist[1] = 0; queue<int>Q; Q.push(1); vis[1] = 1; while(!Q.empty()) { int p = Q.front();Q.pop(); vis[p] = 0; if(cnt[p] > n*2)///说明存在负环,循环次数足够多,就可以让环上的点进队列的次数都大于n; { flag = 1; return ; } for(int i=1; i<=n; i++) { if(dist[i] > dist[p] + G[p][i]) { dist[i] = dist[p] + G[p][i]; if(!vis[i]) { vis[i] = 1; cnt[i]++; Q.push(i); } } } } } int main() { int T, t = 1; scanf("%d", &T); while(T--) { int m, q, u, v; scanf("%d", &n); for(int i=1; i<=n; i++) scanf("%d", &a[i]); Init(); scanf("%d", &m); for(int i=1; i<=m; i++) { scanf("%d %d", &u, &v); G[u][v] = (a[v]-a[u])*(a[v]-a[u])*(a[v]-a[u]); } SPFA(); scanf("%d", &q); printf("Case %d: ", t++); while(q--) { scanf("%d", &u); if(cnt[u]<n && dist[u] != INF && dist[u]>=3) printf("%d ", dist[u]); else printf("? "); } } return 0; }