洛谷 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];View Code5 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 }
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