傳送門
更科學一點的是最大權閉合子圖
popoqqq的題解:
首先我們先把所有的元素都放在集合a中 獲得所有的a[i]和c1[i] 然後考強調內容慮最大權閉合子圖
乙個點如果不選就放在a集合中 選就放在b集合中
乙個點如果選 那麼就要扣除相應的ai並獲得相應的b[i] 於是每個點的權值為b[i]-a[i]
將所有的子集拆點變成兩個
乙個子集中的任意乙個元素選擇 那麼就要扣除相應的c1[i] 這個子集的權值為-c1[i] 從這個子集的所有點出發連一條到達這個點的邊
乙個子集中所有的元素都選擇 那麼就會獲得相應的c2[i] 這個子集的權值為c2[i] 從這個點出發向這個子集的所有點連一條邊
然後建圖跑最大流即可
關於最大權閉合子圖的講解**beginend:
現在有乙個有向圖,每個點有點權,點權可正可負。對於任意一條有向邊i和j,選擇了點i就必須選擇點j,你需要選擇一些點使得得到權值最大。
這個問題可以用網路流解決。
建圖方法:對於任意點i,如果i權值為正,s向i連容量為其權值的邊,否則i向t連容量為其權值的絕對值的邊。原圖所有邊容量為正無窮。則最大權=正權和-最大流。
如何證明呢?我們把最大流理解成最小割,那麼割掉的邊一定不可能是正無窮的邊。
我們發現,選擇乙個正權點即不割掉s到其的邊,選擇乙個負權點即割掉其到t的邊。
現在證明方案合法。
對於依賴關係i到j:
假設i點權為正j點權為負。選了i不選j即沒有割掉s到i的邊而且沒有割掉j到t的邊,顯然s和t聯通,不符合最小割定義。
假設i點權為負j點權為正。選了i不選j即割掉i到t的邊而且割掉s到j的邊,由於s到t現在不連通,我們不割這兩條邊同樣s和t是不聯通的,那麼割這兩邊不滿足割量最小,不符合最小割定義。
其餘情況同理,不符合割量最小。
注意這個演算法不需要原圖是dag。
#include
#include
#include
#include
#include
#include
using
namespace
std;
#define n 4005
#define inf 2000000001
int n,m,a[n],b[n],k,x,c1,c2,s,t,sum,maxflow;
int tot,point[n],nxt[n*1000],v[n*1000],remain[n*1000];
int deep[n],cur[n],last[n],num[n];
queue
q;void addedge(int x,int y,int cap)
void bfs(int t)
}}int addflow(int s,int t)
now=t;
while (now!=s)
return ans;
}void isap(int s,int t)
bool has_find=false;
for (int i=point[now];i!=-1;i=nxt[i])
if (deep[v[i]]+1==deep[now]&&remain[i])
if (!has_find)
}}int main()
}isap(s,t);
printf("%d\n",sum-maxflow);
}
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,然...