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 容量的邊,保證不會出現...