由于本人头铁,这题搞了将近一上午还是爆零
于是颓题解
对于每个点分别记录两个值:到达这个点的最短时间 和 进入这个点的最短时间
前一个值用最短路更新,后一个值用保护它的点的最短路更新
所以本题中一个点的最短路就是 上边的两个值取 max
按题目的道理大力更新最短路即可
代码:
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cctype> #include<cstdio> #include<queue> using namespace std; const int MAXN = 3005, MAXM = 70005; struct EDGE{ int nxt, to, val; EDGE(int NXT = 0, int TO = 0, int VAL = 0) {nxt = NXT; to = TO; val = VAL;} }edge[MAXM << 1]; int n, m, totedge; int head[MAXN], rem[MAXN], d1[MAXN], d2[MAXN]; bool vis[MAXN], pro[MAXN], to[MAXN]; priority_queue<pair<int,int> > q; inline void add(int x, int y, int v) { edge[++totedge] = EDGE(head[x], y, v); head[x] = totedge; return; } inline void dij() { d1[1] = d2[1] = 0; to[1] = true; q.push(make_pair(0, 1)); while(!q.empty()) { int x = q.top().second; q.pop(); if(vis[x]) continue; vis[x] = true; int cur = max(d1[x], d2[x]); for(int i = head[x]; i; i = edge[i].nxt) { int y = edge[i].to; if(edge[i].val != 0x3f3f3f3f) { if(d1[y] > cur + edge[i].val) { to[y] = true; d1[y] = cur + edge[i].val; if(!rem[y]) q.push(make_pair(-max(d1[y], d2[y]), y)); } } else { --rem[y]; if(!rem[y]) { d2[y] = cur; if(to[y]) q.push(make_pair(-max(d1[y], d2[y]), y)); } } } } return; } int main() { scanf("%d%d", &n, &m); register int xx, yy, vv; for(int i = 1; i <= m; ++i) { scanf("%d%d%d", &xx, &yy, &vv); if(xx == yy) continue; add(xx, yy, vv); } for(int i = 1; i <= n; ++i) { d1[i] = 0x3f3f3f3f; d2[i] = 0; scanf("%d", &vv); rem[i] += vv; pro[i] = vv; while(vv--) { d2[i] = 0; scanf("%d", &xx); add(xx, i, 0x3f3f3f3f); } } dij(); printf("%d ", max(d1[n], d2[n])); return 0; }