首先明确最短路是DP 带继承的DP 是有转移的
bellman没有顺序的松弛 复杂度很高 dijk维护一个正解点集 很快
这道题给最短路加了限制:同时走若干条路,当走过某些点后才能走该点
原转移为:d[x] = min {d[y] + w | y -> x}
新加的转移为:d[x] = max {d[y] | y protect x}
可以知道 依然可以维护一个正解点集 当没有protect才可以加入点集
我犯的错误:
longlong
莫名TLE的原因很可能是数组开小 相信复杂度计算
可能会补充手写堆dijk
我TM显然是不会补了!!!!wtf lazyboy! -State 010913
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <vector> 3 #include <cstring> 4 using namespace std; 5 int n, m; 6 typedef __int64 ll; 7 const int N = 10000, M = 200000; 8 const ll INF = 1LL << 60; 9 int key[M], head[N], next[M], len[M], cnt, in[N]; 10 ll d[N]; 11 vector<int> vc[N]; 12 vector<int>::iterator it; 13 inline void add (int x, int y, int w) 14 { 15 key[cnt] = y; 16 next[cnt] = head[x]; 17 len[cnt] = w; 18 head[x] = cnt ++; 19 } 20 inline void dijk () 21 { 22 bool v[N] = {}; 23 for (int i = 0; i <= n; i ++) 24 d[i] = INF; 25 d[1] = 0; 26 for (int i = 1; i <= n; i ++) 27 { 28 int k = 0; 29 for (int j = 1; j <= n; j ++) 30 if (!v[j] && in[j] == 0 && d[j] < d[k]) 31 k = j; 32 v[k] = true; 33 if (k == n) break; 34 for (int j = head[k]; ~ j; j = next[j]) 35 d[key[j]] = min (d[key[j]], d[k] + len[j]); 36 for (it = vc[k].begin (); it != vc[k].end (); it ++) 37 { 38 in[*it] --; 39 d[*it] = max (d[*it], d[k]); 40 } 41 } 42 } 43 int main () 44 { 45 memset (head, -1, sizeof head); 46 scanf ("%d%d", &n, &m); 47 for (int i = 1, a, b, c; i <= m; i ++) 48 scanf ("%d%d%d", &a, &b, &c), add (a, b, c); 49 for (int i = 1, x, y; i <= n; i ++) 50 { 51 scanf ("%d", &x); 52 in[i] = x; 53 while (x --) scanf ("%d", &y), vc[y].push_back (i); 54 } 55 dijk (); 56 printf ("%I64d", d[n]); 57 return 0; 58 }