spfa+优先队列。刚开始只用的spfa,结果tle到死。然后听队友说要用到优先队列,想了想,对时间分层的话的确每一个结点都只进队列一次即可,因为只有大时间才能更新出小时间,然后就wa成shi了。按队友写的改了才过得,好伤心的说,这是好题。。。
附上代码供大家对拍吧。
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<queue> #include<cmath> #define LL long long #define CLR(a, b) memset(a, b, sizeof(a)) #define REP(i, n) for(int i = 0; i < n; i ++) #define FF(i, a, b) for(int i = a; i < b; i ++) #define FD(i, a, b) for(int i = a; i >= b; i --) #define swp(a, b) a^=b^=a^=b; using namespace std; struct Node { int u, b, vd, t; Node(){} Node(int a, int b, int c, int d):u(a), b(b), vd(c), t(d){} bool operator < (const Node &rhs) const { return t < rhs.t; } }; struct Edge { int u, v, t, m; Edge(){} Edge(int a, int b, int c, int d):u(a), v(b), t(c), m(d){} }E[420]; int fir[220], next[440], tot; void Add_Edge(int u, int v, int t, int m) { E[tot] = Edge(u, v, t, m); next[tot] = fir[u]; fir[u] = tot ++; } int dp[110][6][7][220]; bool vis[110][6][7][220]; int p[110][7]; int N, M, B, K, R, T; priority_queue<Node>q; void relax(int u, int b, int vd, int t, int val) { if ((u == 1 || u == N) && vd != 0) return ; if(dp[u][b][vd][t] < val) { dp[u][b][vd][t] = val; if(!vis[u][b][vd][t]) { Node w = Node(u, b, vd, t); q.push(w); vis[u][b][vd][t] = true; } } } void spfa() { int u, v, m, t,vd, b; Node a = Node(1, 0, 0, T); CLR(dp, -1);CLR(vis, false); dp[1][0][0][T] = R; vis[1][0][0][T] = true; q.push(a); while(!q.empty()) { a = q.top();q.pop(); u = a.u;b = a.b;vd = a.vd;t = a.t; if(u == N) continue; if(t > 0) { int val = dp[u][b][vd][t]; relax(u, b, (vd + 1) % K, t - 1, val); if(p[u][vd] != -1) { if(b > 0) { relax(u, b - 1, (vd + 1) % K, t - 1, val + p[u][vd]); } if(b < B && val >= p[u][vd]) { relax(u, b + 1, (vd + 1) % K, t - 1, val - p[u][vd]); } } } for(int i = fir[u]; ~i; i = next[i]) { int tmp = t - E[i].t; if(tmp < 0) continue; v = E[i].v; int val = dp[u][b][vd][t] - E[i].m; if(val < 0) continue; relax(v, b, vd, tmp, val); if(p[u][vd] != -1) { if(b > 0) { relax(v, b - 1, vd, tmp, val + p[u][vd]); } if(b < B && val >= p[u][vd]) { relax(v, b + 1, vd, tmp, val - p[u][vd]); } } } } } int main() { int Time, cas = 1; scanf("%d", &Time); while(Time --) { scanf("%d%d%d%d%d%d", &N, &M, &B, &K, &R, &T); for(int i = 0; i < K; i ++) { for(int j = 1; j <= N; j ++) { scanf("%d", &p[j][i]); } } CLR(fir, -1);tot = 0; int u, v, t, m; for(int i = 0; i < M; i ++) { scanf("%d%d%d%d", &u, &v, &t, &m); Add_Edge(u, v, t, m); } spfa(); int ans = -1; for(int i = 0; i <= B; i ++) { for(int j = 0; j <= T; j ++) { ans = max(ans, dp[N][i][0][j]); } } if(ans != -1) printf("Case #%d: %d\n", cas ++, ans); else printf("Case #%d: Forever Alone\n", cas ++); } }