我們如果要選擇一種種植情況的話,一定是其他的選擇都不可行了。這種決策問題用最小割來處理最好不過。
建圖方式——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,然...