有兩塊容量為無限大的耕地a,b。對於每一種種子,種在a裡的收益為ai,種在b裡的收益為bi。特別地,對於m種組合,如果組合中的種子全部種在a裡,可以獲得c1的額外收益,全部種在b裡則可以獲得c2的額外收益。求最大的收益。
我們考慮對於一種種子要不在a地,要不在b地。當我們取其中一種情況時,就要把另一種捨去。如果在圖上有一條邊連線當前的種子和a,我們就要把將它和b連起來的邊斷開。
這不就是最小割嗎?!
但怎麼建圖呢?
顯然我們可以取a為源點,取b為匯點。對於任意一點,我們連一條從a到當前點的邊,容量為ai,再連一條從當前點到b的邊,容量為bi。
以上是最普通的情況,那麼對於那m種組合,我們應該怎麼去處理呢?
假設現在有一種組合對應著乙個點集,只要u和v中的任意乙個不在a中,我們就無法得到c1的額外收益。我們肯定不可以分別從a連向u,v,因為這個樣子即使到v的邊斷了,到u的邊依然有可能會使c1的額外收益流到匯點,但這並不合題意。
也就是說,我們需要有一條邊滿足只要這條邊被割斷,那麼c1的額外收益就肯定不會流到匯點。
那麼這條邊應該由a連向誰呢?顯然不可能是圖中原有的點了,因為不管是c1還是c2,都是這整個組合的額外收益,所以c1要能流入這個點集中的任意乙個點。
那麼解決方案就十分明顯了——建乙個虛點x,從a連一條邊到x,邊的容量為c1;再從x連向點集中的每乙個點,邊的容量為無窮大,即無法被割斷。
對於點集裡的點到b中的處理與以上相同。
根據最大流=最小割,我們只要在建好的圖上跑一遍最大流,並用所有的值減去求出的最小割(最少的取不到的價值),就能求出答案了。
這道題加了許多虛點和虛邊,所以陣列大小至少要為1e7
#include#define maxn 1000009
#define inf 0x7fffffff
using namespace std;
int cnt,to[maxn*2],val[maxn*2],next[maxn*2],head[maxn],cur[maxn*2];
int n,m,s,t,a[maxn],b[maxn],k,c1,c2,d[maxn],sum;
long long ans,all;
void add (int x,int y,int z)
void read ()
for (int i=1;i<=n;i++)
scanf("%d",&m);
sum=0;
for (int i=1;i<=m;i++)
add(n+sum+2+1,t,c2),add(t,n+sum+2+1,0);//連線點集和b的虛點
sum++; }}
bool bfs ()
} } if (d[t]!=-1)
return true;
else
return false;
}int dfs (int x,int low)
} if (low!=0)
d[x]=-1;
return totflow;
}void dinic ()
int main ()
{ cnt=-1;
memset(head,-1,sizeof(head));
read();
dinic();//跑一遍dinic
cout《剛學dinic,急著把板子揹著寫一遍,結果最後忘了要用總答案減去最小割,白調了半天tat
洛谷 P1361 小M的作物
有 nn n 種作物,兩塊耕地 a aa 和 bbb 第 i ii 種作物種植在 a aa 中收益為 a ia i ai 種植在 b bb 中收益為 b ib i bi 另有 m mm 種組合,每種組合有 k kk 種作物,如果這 k kk 種作物共同種在 a aa 中收益為 c1i c1 i c1...
P1361 小M的作物
p1361 小m的作物 二者取其一型別的網路流題 不同的集合,向對應元素連去不同 收益 容量的邊 對於那些神奇的組合,我們只需要按照以下方式建立兩個點 x 向 s 連一條在a時的額外收益 2.x x 注意順序,x 是其有向邊的起點,x 是其有向邊的終點 向其後繼節點連 inf 容量的邊,保證不會出現...
P1361 小M的作物
小m在mc裡開闢了兩塊巨大的耕地a和b 你可以認為容量是無窮 現在,小p有n中作物的種子,每種作物的種子有1個 就是可以種一棵作物 用1.n編號 現在,第i種作物種植在a中種植可以獲得ai的收益,在b中種植可以獲得bi的收益,而且,現在還有這麼一種神奇的現象,就是某些作物共同種在一塊耕地中可以獲得額...