筆記 - 0/1分數規劃
阿新 • • 發佈:2022-03-01
圖論 0/1分數規劃的筆記與題目
題目
-
放棄測試 模板 0/1 分數規劃
-
sightseeing cows 典 0/1 分數規劃 + SPFA判負環
這題好像不能用dinkelbach
迭代法 -
沙漠之王 典 0/1 分數規劃 + Prim
關於 dinkelbach 迭代法完虐二分法的這件事
《進階指南》中關於
0/1分數規劃
介紹的末尾, 挖了個dinkelbach演算法
的坑
我遂網上衝浪了一下, 找到了這篇 優秀的大佬的令人orz的部落格有多快
在 放棄測試 中,
dinkelbach
以五倍的速度完虐二分法
在此題也同樣穩定地五倍吊打著
核心思想
(我講不好..具體看上面的那篇部落格)
函式 \(f(x)=\sum A_ic_i-x\sum B_ic_i\)
求出 \(x\) 對應的 \(f_{x_{max}}\) 後, 二分演算法僅僅判斷了\(f_{x_{max}}\) 與 \(0\) 的關係
但其實將 \(f_{x_{max}}\) 利用起來, 找到 \(f_{x_{max}}\) 所在的那條直線, 然後將 \(x\) 移到這條直線的截距上去, 就可以實現極速定位程式碼
double dinkelbach(){ double x=0, ans, p, q; while(true){ ans=x, p=0, q=0; REP(i, 0, n) dis[i]=INF, vis[i]=false; dis[1]=0; REP(_, 1, n){ // Prim O(N^2) int u=0; REP(v, 1, n) if(!vis[v] && dis[v] < dis[u]) u=v; vis[u] = true; if(u!=1) p += c[pre[u]][u], q += d[pre[u]][u]; REP(v, 1, n) if(!vis[v] && dis[v] > c[u][v]-d[u][v]*x) dis[v] = c[u][v]-d[u][v]*x, pre[v]=u; } x = p/q; // 直接移動到截距上 if(fabs(ans-x)<eps) break; // 沒有更優了, 退出 } return ans; // 即為最終答案 }
但似乎
dinkelbach
並不能完全取代二分, 可能在某些場景前者並不適用, 所以最好兩種方法都掌握.
迭代法不適用的場景之一: 0/1分數規劃 + SPFA判負環