[Wf2011]Chips Challenge(最小费用最大流)
[Wf2011]Chips Challenge
- problem
- solution
- code
problem
BZOJ2673
solution
.
首先得知道這是網絡流,但真的看不出來啊!!我真的郁悶啊( ̄﹏ ̄;)
在知道做法是網絡流后,初讀題,肯定會想到將行列分左右點,[1,n][1,n][1,n]表示行,[n+1,2n][n+1,2n][n+1,2n]表示列。
然后就發現舉步維艱,因為題目要維護的兩個條件都不是很好操作。
iii 行 iii 列零件數一樣,且每行零件數不能超過總數的 AB\frac{A}{B}BA?。
這兩個限制條件都沒有明確具體零件個數要求,是隨著全局動態變化的。
所以無法變成網絡流上的容量限制。
唯一知道的限制就是每行每列可放芯片的最大數量。
【可放指的是 . /C 的點】
注意到 nnn 的限制很小,不妨考慮枚舉每行可放零件的最大值個數 MaxMaxMax。
如果能通過網絡流求出總零件數量 tottottot,就可以逆向判斷 Max≤ABtot?Max?B≤A?totMax\le \frac{A}{B}tot\Rightarrow Max*B\le A*totMax≤BA?tot?Max?B≤A?tot。
而網絡流是最大流,是盡量做到流滿的,所以 tottottot 一定會盡可能的大。
增長同向平行,最大流就是在做盡量滿足判斷式子的過程。
所以如果最大流的結果還是不滿足上面的不等式,只能說明 MaxMaxMax 不是合法的。
自然地想到,對于可放芯片的位置 (i,j)(i,j)(i,j) 進行 iii 行向 jjj 列連邊,容量為 111 。
這樣去跑網絡流,跑出的最大流確實是最多能放的芯片數量,但是這樣并沒有考慮到 iii 行 iii 列相等的限制。
因為不能知道第 iii 行和第 iii 列具體放了多少個芯片,沒有明確的容量限制。
但是轉化一下,第 iii 行放了芯片的位置和第 iii 列沒放芯片的位置加起來一共是等于 nnn 的。
所以想到新建一個連接點 kkk,分別讓行列點向 kkk 連邊。
行連接的邊流過的流量來表示行放芯片的個數,列連接的邊流過的流量來表示列不放芯片的個數。
行列與 kkk 之間的邊容量設為 ∞∞∞。
然后連接點向 ttt 連邊,容量為 nnn,保證 k→tk\rightarrow tk→t 的邊滿流即可。
因為這樣代表著第 iii 行放的個數和第 iii 列不放的個數加在一起是等于 nnn 的,變相地滿足第 iii 行和第 iii 列個數相同的限制。
但是怎么能一些邊流了表示不選,一些邊流了表示要選。最大流上面看到了是不能做到的,那就只能考慮最小費用了。
行 iii 流給連接點 kkk 的表示要放的芯片,列 iii 流給 kkk 的表示不放的芯片,所以 i→ji\rightarrow ji→j 這種流給其它列點就應當表示 (i,j)(i,j)(i,j) 不放芯片,所以只有 iii 行 jjj 列是 . 才有選擇不放的可能。
為了記錄這樣的邊流了多少,就把這種邊帶上費用 111,跑最小費用就是盡可能減少不放的,即最大化放的芯片。
除了這樣的邊,其余邊費用就為 000,屬于要跑最大流。
別忘了,一開始枚舉的每行放芯片個數的限制,所以行與連接點之間的容量應該修改為 MaxMaxMax。
注意到,現在的網絡還有一個冗余的地方,列 iii 的出邊只有連接點 kkk,且容量為 ∞∞∞,所以可以將列 iii 與連接點進行合并。
那么現在的網絡,行 iii 的流量只有兩種去向:經過列 iii 最多流 MaxMaxMax 個,剩下的都是流到其他列 jjj 地方,表示不放芯片,且帶有費用 111。
最后最大流減去最小費用就是真正放的芯片個數,再減去一定放的 C 個數就是新放的芯片個數。
最后記得還有行列分別與源匯的連邊。
通過 s→is\rightarrow is→i 容量為第 iii 行可放的芯片數量來限制第 iii 行放置的個數。
通過 j→tj\rightarrow tj→t 容量為第 jjj 列可放的芯片數量來限制第 jjj 列放置的個數。【準確來說是 j+n→tj+n\rightarrow tj+n→t,大家意會就行】
最后讓這個網絡滿流即可。
總結一下建圖過程:
{s→irowi,0i+n→ncoli,0i→j+n1,1(ch[i][j]=′.′)i→i+nMax,0\begin{cases}s\rightarrow i\quad \quad \quad row_i,0\\i+n\rightarrow n\quad col_i,0\\i\rightarrow j+n\quad 1,1\ (ch[i][j]='.')\\i\rightarrow i+n\quad Max,0\end{cases} ??????????s→irowi?,0i+n→ncoli?,0i→j+n1,1?(ch[i][j]=′.′)i→i+nMax,0?
code
#include <bits/stdc++.h> using namespace std; #define maxn 105 #define maxm 5005 int n, a, b, s, t, cnt; bool vis[maxn]; char ch[maxn][maxn]; int dis[maxn], head[maxn], lst[maxn], row[maxn], col[maxn]; struct node { int to, nxt, flow, w; }E[maxm]; queue < int > q;void addedge( int u, int v, int flow, int w ) {E[cnt] = { v, head[u], flow, w };head[u] = cnt ++;E[cnt] = { u, head[v], 0, -w };head[v] = cnt ++; }bool spfa() {memset( dis, 0x7f, sizeof( dis ) );memset( lst, -1, sizeof( lst ) );dis[s] = 0; q.push( s );while( ! q.empty() ) {int u = q.front(); q.pop(); vis[u] = 0;for( int i = head[u];~ i;i = E[i].nxt ) {int v = E[i].to;if( dis[v] > dis[u] + E[i].w and E[i].flow ) {dis[v] = dis[u] + E[i].w;lst[v] = i;if( ! vis[v] ) vis[v] = 1, q.push( v );}}}return ~ lst[t]; }void MCMF( int &flow, int &cost ) {flow = cost = 0;while( spfa() ) {int Min = 1e9;for( int i = lst[t];~ i;i = lst[E[i ^ 1].to] )Min = min( Min, E[i].flow );for( int i = lst[t];~ i;i = lst[E[i ^ 1].to] )cost += E[i].w * Min, E[i].flow -= Min, E[i ^ 1].flow += Min;flow += Min;} }int main() {int Case = 0;while( ~ scanf( "%d %d %d", &n, &a, &b ) ) {if( ! n and ! a and ! b ) break;memset( row, 0, sizeof( row ) );memset( col, 0, sizeof( col ) );s = 0, t = n << 1 | 1;int sum = 0, used = 0;for( int i = 1;i <= n;i ++ ) {scanf( "%s", ch[i] + 1 );for( int j = 1;j <= n;j ++ )if( ch[i][j] != '/' ) {sum ++, row[i] ++, col[j] ++;used += ch[i][j] == 'C';}}int ans = -1;for( int Max = 0, flow, cost;Max <= n;Max ++ ) {memset( head, -1, sizeof( head ) ); cnt = 0;for( int i = 1;i <= n;i ++ ) {addedge( s, i, row[i], 0 );addedge( i + n, t, col[i], 0 );addedge( i, i + n, Max, 0 );for( int j = 1;j <= n;j ++ )if( ch[i][j] == '.' ) addedge( i, j + n, 1, 1 );}MCMF( flow, cost );if( flow == sum and Max * b <= ( sum - cost ) * a )ans = max( ans, sum - cost );}printf( "Case %d: ", ++ Case );if( ~ ans ) printf( "%d\n", ans - used );else printf( "impossible\n" );}return 0; }總結
以上是生活随笔為你收集整理的[Wf2011]Chips Challenge(最小费用最大流)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么解绑辅助账号(怎么解绑辅助账号手机)
- 下一篇: AtCoder Regular Cont