網路流應用

2022-08-20 03:18:11 字數 2714 閱讀 6415

cf1264e beautiful league

cf1264e beautiful league

先反其道而行之,如果 \((a,b,c)\) 不符合條件,一定有某乙個隊伍贏了另外兩個隊。進一步,如果 \(x\) 隊贏了 \(c_x\) 局,不滿足條件的三元組數量 \(number=\sum\frac\)。目的就是讓這個東西盡量小

現在有一些的比賽結果已經固定,相當於每個 \(c_x\) 有乙個限制:\(c_x\in [l_x,r_x]\) 且 \(\sum c_x=\frac\)。如果沒有這個限制當然可以根據不等式直接取值,但加上限制後似乎沒法直接貪心。(不然為什麼資料範圍這麼小呢)

改用費用流。每場比賽乙個節點,每個隊伍乙個節點。連這幾種邊:

1、\(s\) 到所有比賽節點連一條容量為 \(1\),花費為 \(0\) 的邊,代表這場比賽贏家只有乙個。

2、每場比賽向對應的兩支隊伍連邊,容量 \(1\),花費 \(0\)

3、每支隊伍向 \(t\) 連 \(n-p_x-1\) 條邊,\(p_x\) 為固定的已經贏的場數。每條邊的容量為 \(1\),花費為每次多贏一場後 \(\frac\) 的增量

在這張圖上求最小費用最大流就是答案

#include using namespace std;

void read (int &x) const int n = 52, p = n * n, m = n * 600;

int n, m, s, t, tot, k[n][n], c[n], idm[n][n], id[n];

int cnt = 1, h[m], nxt[m], to[m], w[m], co[m];

void add (int u, int v, int ww, int cc)

queueq; int d[p], f[p], in[p], pre[p];

int spfa ()

}return (d[t] != d[t + 1]);

}void update ()

}signed main()

s = 0, t = ++tot;

for (int i = 1; i <= n; ++i)

for (int j = c[i]; j < n; ++j) add (id[i], t, 1, j);

while (spfa ()) update ();

for (int i = 1; i <= n; ++i)

for (int j = i + 1; j <= n; ++j)

if (idm[i][j])

for (int i = 1; i <= n; ++i)

}

cf1430g yet another dag problem(2020-11-10)

cf1430g yet another dag problem

把邊的貢獻放到點上,點權的值域和點的個數同級且非常少,把每個點選每個值的貢獻當作邊權建圖

但是有限制,即一條邊的 \(u\) 的值大於 \(v\) 的值。可以在 \(v\) 選每個值 \(p\) 的地方向 \(u\) 取 \(p+1\) 的地方連 \(inf\) 邊

然後求最小割。這個限制相當於如果 \(v\) 取了 \(p\),那 \(u\) 取 \(p\) 之前的都是白取,不會算在最小割內

注意點是每條邊的權值要平移至正數

cf1354f summoning minions(2020-11-14)

cf1354f summoning minions

這個題自己想了一半,但最後建圖不是像上面那樣拆開,沒有想出來,但其實dp更簡單

先貪心一波,假設最後留下的 \(k\) 個點已經選好了,最優方案把這些點按照 \(b_i\) 排序,前 \(k-1\) 個在最開始放入,然後隨便放入沒有選中的點(放入馬上刪除),最後放入第 \(k\) 個點

先假設所有點都沒被選中,按照公式算出總答案,用網路流跑選 \(k\) 個點的最優解。發現把第 \(i\) 個點選成 \(k\) 中第 \(j\) 個帶來的變化是可以算的,這個自然作為邊權

與上面不同的是,如果拆開每個點,每個點只能選一次的限制不是很好考慮。其實方法比上面更簡單,直接用二分**決。左部 \(n\) 個點為每個點,右部 \(k\) 個點為把它選中為第幾個,連邊跑費用流

arc107f - sum of abs (2020-11-02)

f - sum of abs

和上一題比較類似,先把所有的弄成某個狀態,然後把改變狀態帶來的改變價值當作邊權,但是這個稍微難理解一些。

乙個連通塊中,如果總和是負數,相當於所有點的權值 \(\times -1\),否則 \(\times 1\)

在答案中每個點都是被成上了 \(+1\) 或 \(-1\) 的權值或被刪除,三種狀態。限制是沒刪除的相連的點乘上的值相同

先建立基本的模型,對於每個點拆成 \(2\) 個,從源點到第乙個點,從第乙個點到第二個點,從第二個點到匯點,代表 \(3\) 中狀態

一開始的答案為所有點的絕對值之和,那麼網路流模型中每條邊的邊權是可以弄出來的。

只剩下新增限制了。設從第乙個點連到第二個點的表示刪除的代價。對於每條邊 \((u,v)\),從 \(u\) 的二號點到 \(v\) 的一號點連 \(inf\) 邊,從 \(v\) 的二號點到 \(u\) 的一號點連 \(inf\) 邊

意義就是如果 \(u\) 選擇刪除,\(v\) 隨意(因為從一號到二號的邊已經沒了),如果選了 \(+1\) 或 \(-1\),\(v\) 只能刪除或選同樣的權值(如果選了不同的兩邊還是通的,沒有意義)。跑最小割就是答案

網路流 費用流

這個好像不考 沒事可以騙分 費用流,顧名思義,就是有費用的流,也就是說,給乙個網路流圖中的每條弧增加乙個單位流量費用。一般來說求解的費用流都是最大流最小費用。好像沒什麼好bb的 這裡推薦使用zkw演算法求解最小費用流,看著 理解就行,應該還是很好理解的。zkw演算法在稠密圖上跑得飛快,在稀疏圖上還不...

網路流 費用流

網路流有很多種類 其中最大流 有增廣路演算法和預流推進演算法。增廣路演算法就是不斷的新增增廣路。其中的dinic演算法。會稍微提到isap演算法 poj1273 首先想到dfs一直往後延伸,然後從源點到匯點計算每條路,但是這樣只是單條路的最值,有時可能因為走一條路而間接的認定了除這條路以外的某個路通...

網路流之費用流

求費用流目前好像只有ek spfa改版,時間複雜度為o n e k 其中k為最大流值。但時間上的期望時間複雜度為 o a e k 其中a為所有頂點進佇列的平均次數,可以證明a一般小於等於2。最小費用最大流 include using namespace std const int inf 0x3f3...