洛谷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 }
AC代码

 

posted @ 2018-10-16 14:18  huyufeifei  阅读(151)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜