洛谷P2446 大陆争霸
这是一道dijkstra拓展......不知道为什么被评成了紫题。
有一个很朴素的想法就是每次松弛的时候判断一下那个点是否被保护。如果被保护就不入队。
然后发现写起来要改的地方巨多无比......
改到最后应该是用2/3个数组,分别表示最早可达时间(time),最早无防护时间(ruin)。以及一个取它们最大值的数组(ed),表示真实摧毁时间。
然后每次当一个点被某种更新之后入度变成0了,就用ed入队。
如果一个点出队了,就vis,然后不可被更新,然后更新某些点的入度,ruin和time。
这个正确性应该是有的:此后更新的每个点的ed都不会比当前点的ed小。
代码上两种更新的先后顺序不会影响结果。
1 #include <cstdio> 2 #include <queue> 3 #include <algorithm> 4 #define mp std::make_pair 5 6 typedef long long LL; 7 const int N = 3010, M = 100010; 8 const LL INF = 1ll << 60; 9 10 struct Edge { 11 int nex, v; 12 LL len; 13 }edge[M << 1], _edge[M << 1]; int top, _top; 14 15 int e[N], _e[N], n, in[N]; 16 bool vis[N]; 17 LL time[N], ruin[N], ed[N]; 18 19 inline void add(int x, int y, LL z) { 20 top++; 21 edge[top].v = y; 22 edge[top].len = z; 23 edge[top].nex = e[x]; 24 e[x] = top; 25 return; 26 } 27 28 inline void _add(int x, int y) { 29 _top++; 30 _edge[_top].v = y; 31 _edge[_top].nex = _e[x]; 32 _e[x] = _top; 33 return; 34 } 35 36 std::priority_queue<std::pair<LL, int> > Q; 37 38 inline void BFS() { 39 40 Q.push(mp(-1, 1)); 41 ed[1] = 1; 42 ruin[1] = 1; 43 time[1] = 1; 44 45 int x; 46 while(!Q.empty()) { 47 x = Q.top().second; 48 Q.pop(); 49 if(vis[x]) { 50 continue; 51 } 52 vis[x] = 1; 53 for(int i = e[x]; i; i = edge[i].nex) { 54 int y = edge[i].v; 55 if(vis[y]) { 56 continue; 57 } 58 if(time[y] > ed[x] + edge[i].len) { 59 time[y] = ed[x] + edge[i].len; 60 if(!in[y]) { 61 ed[y] = std::max(ruin[y], time[y]); 62 Q.push(mp(-ed[y], y)); 63 } 64 } 65 } 66 67 for(int i = _e[x]; i; i = _edge[i].nex) { 68 int y = _edge[i].v; 69 in[y]--; 70 ruin[y] = std::max(ruin[y], ed[x]); 71 if(!in[y]) { 72 ed[y] = std::max(ruin[y], time[y]); 73 Q.push(mp(-ed[y], y)); 74 } 75 } 76 } 77 78 if(ruin[n] >= INF) { 79 printf("Mission Failed"); 80 return; 81 } 82 printf("%lld", std::max(ruin[n], time[n]) - 1); 83 84 /*for(int i = 1; i <= n; i++) { 85 printf("%d ruin = %lld time = %lld \n", i, ruin[i], time[i]); 86 } 87 puts("");*/ 88 89 return; 90 } 91 92 int main() { 93 //freopen("bomb.in", "r", stdin); 94 //freopen("bomb.out", "w", stdout); 95 96 int m; 97 scanf("%d%d", &n, &m); 98 for(int i = 1, x, y; i <= m; i++) { 99 LL z; 100 scanf("%d%d%lld", &x, &y, &z); 101 add(x, y, z); 102 //add(y, x, z); 103 } 104 for(int i = 1, k, x; i <= n; i++) { 105 scanf("%d", &k); 106 for(int j = 1; j <= k; j++) { 107 scanf("%d", &x); 108 _add(x, i); 109 in[i]++; 110 } 111 time[i] = INF; 112 } 113 time[n] = INF; 114 115 BFS(); 116 117 /*puts(""); 118 for(int i = 1; i <= n; i++) { 119 printf("%d ruin = %lld time = %lld \n", i, ruin[i], *(time + i)); 120 }*/ 121 122 return 0; 123 }