1. 程式人生 > 其它 >洛谷 P5469 - [NOI2019] 機器人(區間 dp+拉格朗日插值)

洛谷 P5469 - [NOI2019] 機器人(區間 dp+拉格朗日插值)

  最大流:dfs下由於目標不確定性使得使非最大流集合的路徑

消耗流改變原圖結構,從而無法遍歷出正解

  於是考慮反悔,建立反向邊殘量網路,考慮意義,若存在一條

路徑經過反向邊,代表存在另一種增廣路的選擇,觀察反向邊路徑

發現,其本質為將之前已經運輸的流量運輸到另一位置,也就是反

悔,而當圖中不存在殘量網路時,代表當前狀態下已經不存在一種

可能的增廣路,由於最大流必定為一種固定狀態,此時當不存在可

能路徑時,即為最大流狀態(dfs性質決定),事實上其本質為遍歷

每一種可能情況直至找到目標狀態。

思想:逆向儲存建立反悔系統,固定狀態存在的必然性,構造法

  EK優化:由於鄰接表遍歷的限制,單純帶悔dfs存在的致命缺陷

為目標的不確定性(但一定會找到目標),這導致演算法效率的不確定

性,於是EK演算法對於FF演算法的優化就在於賦予程式以一定的順序,

將dfs改為bfs,每次遍歷最短增廣路,可知增廣次數在於每條邊滿流

的次數之和,而一條邊滿流代表增廣路長度的增加(邏輯證明),增

廣路最多增加V次於是演算法複雜度O(VE^2)

思想:不確定性演算法的優化->賦予演算法以一定順序,複雜度證明

程式碼如下:

 1 namespace Edmonds_Krap {
 2         LL maxflow;
 3         I flow[N],pre[N];
 4         B jud[N];
5 B bfs () { 6 memset (jud,0,sizeof jud); 7 queue <I> q; 8 q.push (s); jud[s] = 1; 9 flow[s] = INT_MAX; 10 while (!q.empty ()) { 11 I x (q.front ()); q.pop (); 12 for (I i(head[x]); i ;i = nxt[i])
13 if (wgt[i] && !jud[to[i]]) { 14 flow[to[i]] = min (flow[x],wgt[i]); 15 pre[to[i]] = i; 16 if (!(to[i] ^ t)) return true; 17 q.push (to[i]); jud[to[i]] = 1; 18 } 19 } 20 return false; 21 } 22 V update () { 23 I x (t); 24 while (x != s) { 25 wgt[pre[x]] -= flow[t]; wgt[pre[x] ^ 1] += flow[t]; 26 x = to[pre[x] ^ 1]; 27 } 28 maxflow += flow[t]; 29 } 30 V Edmonds_krap () { while (bfs ()) update (); } 31 }
View Code

  DC優化:容易發現EK優化演算法複雜度瓶頸在於每次只拓展一條

增廣路,這樣許多上流量將被浪費,於是考慮充分利用上流量進行多

路拓展,為了保證複雜度,仍然需要保證拓展的有序性,於是選擇在

分層圖上進行拓展,當前節點流量對子節點進行多次拓展,容易發現

此情況下dfs無法標記成為指數級演算法,考慮優化無用遍歷,發現當一

條路徑流量被充分利用時,下一次拓展不會造成新的貢獻,於是考慮

記錄已經不會造成貢獻的節點避免下次遍歷。需要注意的是,當前弧

優化須注意避免最後一個節點被略過,考慮for執行順序合理設計即可

思想:充分利用資源進行拓展,避免冗餘遍歷,時間複雜度優化

程式碼如下:

 1 namespace Dinic {
 2         LL maxflow;
 3         I d[N],now[N];
 4         B bfs () {
 5             memset (d,0,sizeof d);
 6             memcpy (now,head,sizeof head);
 7             queue <I> q;
 8             q.push (s); d[s] = 1;
 9             while (!q.empty ()) {
10               I x (q.front ()); q.pop ();
11               for (I i(head[x]); i ;i = nxt[i])
12                 if (wgt[i] && !d[to[i]]) {
13                   d[to[i]] = d[x] + 1;
14                   if (! (to[i] ^ t)) return true;
15                   q.push (to[i]); 
16                 }
17             }
18             return false;
19         }
20         I dfs (I x,I flow) {
21             if (! (x ^ t)) return flow;
22             I rest (flow),i,sup;
23             for (i = now[x]; i ;i = nxt[i])
24               if (wgt[i] && d[to[i]] == d[x] + 1) {
25                 sup = dfs (to[i],min (rest,wgt[i]));
26                 if (!sup) d[to[i]] = 0;
27                 wgt[i] -= sup, wgt[i ^ 1] += sup; rest -= sup;
28                 if (!rest) { now[x] = i; break; }
29               }
30             return flow - rest; 
31         }
32         V dinic () { while (bfs ()) maxflow += dfs (s,INT_MAX); }
33     }
View Code