BZOJ3438 小M的作物(和拓展)

2022-03-03 17:03:07 字數 1591 閱讀 6172

我們如果要選擇一種種植情況的話,一定是其他的選擇都不可行了。這種決策問題用最小割來處理最好不過。

建圖方式——a為源點,b為匯點。然後將每個點分別向a,b連邊,邊權為種植它的價值。組合的話,我們考慮新建兩個節點,乙個連a,對應集合中的每個數,連inf;乙個連b,從集合中的每個數向它連inf。

最後的答案是總點權-最小割。割邊表示不選。

如果選擇組合,我們肯定是先割掉了集合中節點一側的所有邊,然後發現組合對應節點還沒有割掉,我們把它割掉就行了,而割掉的這個邊也肯定是同一側的。

如果不選擇組合,我們肯定是割掉了集合中一部分節點的一側邊,一部分節點的另一側邊。這時候我們發現組合對應的這兩個節點,都可以通過組合中節點沒有割掉的邊形成增廣路。所以我們不得不把組合對應的兩個點的邊都割掉,以表示不選這個集合。

**如下:

#include#include#include#include#include#include#define inf 0x3f3f3f3f

#define maxn 100010

#define s 0

#define t n+m*2+1

using namespace std;

int n,m,t=1,ans;

int head[maxn],dep[maxn],a[maxn],b[maxn],cur[maxn];

struct edgeedge[maxn<<4];

inline void add(int from,int to,int dis)

inline bool bfs()

}if(dep[t]==0x3f3f3f3f) return false;

return true;

}inline int dfs(int x,int f)

}return used;

}inline int dinic()

int main()

}for(int i=1;i<=n;i++) add(s,i,a[i]);//rintf("[%d %d] %d\n",s,i,a[i]);

for(int i=1;i<=n;i++) add(i,t,b[i]);//printf("[%d %d] %d\n",i,t,b[i]);

for(int i=1;i<=n;i++) ans+=a[i]+b[i];

printf("%d\n",ans-dinic());

return 0;

}

其實類似的模型還有這道題

這道題不僅是把組合分給a,b的代價不同,而且不要這個組合的話,還需要倒扣錢。

但是思路還是一樣的,我們先把a,b的得分加上,然後組合的a,b,c的得分也都加上。

然後我們這樣子連邊——

add(s,id_a(i),a[i]);

add(id_b(i),t,b[i]);

add(s,id_a(i),ea+ec);

add(id_a(i),u,inf);

add(id_a(i),v,inf);

add(id_b(i),t,eb+ec);

add(u,id_b(i),inf);

add(v,id_b(i),inf);

BZOJ3438 小M的作物

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

bzoj3438 小M的作物

題目鏈結 先考慮沒有額外收益的時候怎麼做。從 s 向第 i 點連一條容量為 a i 邊,表示種在 a 中的收益。從第 i 個點向 t 連一條容量為 b i 的邊,表示種在 b 中的收益。然後求出來最小割,用總收益減去即可。完成之後如下圖 然後考慮如何處理額外收益 對於每乙個額外的收益,我們先新建乙個...

bzoj3438 小M的作物

這題是一道最大權閉合圖的經典難題 by rose max upd 不誤人子弟了,這就是乙個裸的最小割啊。然後構圖的方式就是把作物值分成ab集合,乙個在st一邊,乙個在ed一邊,st連作物流量為a i 作物流ed流量為b i 對於每乙個組合,新建兩個點,乙個被st流流量為c1,乙個流ed流量為c2,然...