最小割 P1361 小M的作物

2022-06-03 08:12:13 字數 1738 閱讀 2065

p1361 小m的作物

建圖好題。

思路

看得出來還是經典的兩者取一模型,也就是找出一種割邊方式,將點劃分為兩個集合,且割邊花費最小。但是給出的是收益而非費用,怎麼辦呢?

最大收益=總收益-最小損失。

總收益就是把題目給出的種a地種b地的收益以及組合的bonus全部加起來。最小損失就是跑最大流(=最小割)。

將種\(a\)地視為源點,種\(b\)地視為匯點。

下面考慮某一種作物的情況:

因為是假設從一開始就有總收益,也就是一種作物既種\(a\)地也種\(b\)地,之後再考慮放棄哪一邊使種植方案可行,所以對於每一種作物\(i\),連邊\(a→i\),\(i→b\)。

再考慮組合bonus:

只有當組合內所有作物都種在同乙個地方才能得到bonus,那麼可以嘗試把整個組合視為乙個點,但我們無法真正地用乙個點代表乙個組合(畢竟不像scc縮點),所以考慮用兩個新點(注意不能用組合內的點,且一定要兩個點)\(x\)和\(y\)作為這個組合的代表,其中\(x\)代表組合種\(a\)地,\(y\)代表組合種\(b\)地。故連邊\(a→x\)和\(y→b\)。而內部的所有點是無法切斷的整體,故對於組合內的點\(corn[i]\),連邊\(x→corn[i]\)和\(corn[i]→y\),邊權均為\(inf\)。

然後跑最大流得出最小割,也就是最小損失,用總收益減去即得答案。

注意總頂點數是\(n+2+m*2\)(\(n\)種作物+源點匯點+每個組合兩個代表點),雖然不知道為什麼寫成\(n+2\)也能過……

const int inf = 2005020600;

const int maxn = 6e4 + 100;

const int maxm = 2e6 + 100;

struct edge e[maxm];

int cnt_e = 0, head[maxn], n, m;

int s, t;

int cur[maxn], depth[maxn], gap[maxn];

int corn[maxn];

ll maxflow = 0;

void addn(int u, int v, ll w)

void bfs()

}return;

}ll dfs(int now, ll minflow,int n)

ll nowflow = 0;

for (int i = cur[now]; i; i = e[i].next)

if (minflow == nowflow) return nowflow;}}

gap[depth[now]]--;

if (!gap[depth[now]]) depth[s] = n + 1;

depth[now]++;

gap[depth[now]]++;

return nowflow;

}ll isap(int n)

return maxflow;

}int main()

f(i, 1, n)

m = read();

f(i, 1, m)

int mincost = isap(n + 2 + m * 2);

//跑最大流,求出的是最小割,也就是最小損失

//答案求的是最大收益,總收益-最小損失即可

printf("%d", sum - mincost);

return 0;

}

P1361 小M的作物 最小割

小m在mc裡開闢了兩塊巨大的耕地a和b 你可以認為容量是無窮 現在,小p有n中作物的種子,每種作物的種子有1個 就是可以種一棵作物 用1.n編號 現在,第i種作物種植在a中種植可以獲得ai的收益,在b中種植可以獲得bi的收益,而且,現在還有這麼一種神奇的現象,就是某些作物共同種在一塊耕地中可以獲得額...

P1361 小M的作物 網路流 最小割

小m在mc裡開闢了兩塊巨大的耕地a和b 你可以認為容量是無窮 現在,小p有n中作物的種子,每種作物的種子有1個 就是可以種一棵作物 用1.n編號 現在,第i種作物種植在a中種植可以獲得ai的收益,在b中種植可以獲得bi的收益,而且,現在還有這麼一種神奇的現象,就是某些作物共同種在一塊耕地中可以獲得額...

P1361 小M的作物

p1361 小m的作物 二者取其一型別的網路流題 不同的集合,向對應元素連去不同 收益 容量的邊 對於那些神奇的組合,我們只需要按照以下方式建立兩個點 x 向 s 連一條在a時的額外收益 2.x x 注意順序,x 是其有向邊的起點,x 是其有向邊的終點 向其後繼節點連 inf 容量的邊,保證不會出現...