bzoj2039 人員僱傭 最小割

2021-07-09 14:45:12 字數 1342 閱讀 3319

這道題目描述真是醉了。。題意,僱傭每乙個經理有乙個花費,同時僱傭兩個經理可以的到2*e[i,j]的利潤,如果乙個經理僱傭另乙個經理不僱傭會造成e[i,j]的損失(注意是倒扣)。

這種題目的做法和最大閉全子圖差不多是乙個道理。。簡單說一下吧(其實是怕自己忘記):

一般來說都是轉化成最小割,割完以後和s相連的是要選取的(對應到本題就是要僱傭的),和t相連的是不選取的,然後割表示損失的部分。因此建圖如下:

首先,對於要僱傭的,要和s相連,就要和t割斷,每乙個點都是如此,因此每乙個點(表示每乙個經理)向t連一條邊,邊權為僱傭的費用,這樣和t相連的就不需要割斷,因此對應不僱傭的;和t割斷的就是要僱傭的;

然後,對於不僱傭的,即要和t相連,和s割斷,那麼它損失的即為乙個經理所能創造的利潤e[i,1]+e[i,2]+...+e[i,n],因此將s向每乙個點連一條邊,容量即剛剛那個式子的結果;

最後,還要考慮損失的部分,即題中的競爭對手。如果按照上面的方法,i,j都僱傭會造成0的損失(因為和s相連的邊不是割),i,j都不僱傭會造成2*e[i,j]的損失(因為和s相連的邊都是割),但是乙個僱傭乙個不僱傭卻只會造成e[i,j]的損失,但實際上損失為e[i,j]*3,因此在i,j中連一條容量為(3-1)*e[i,j]=2*e[i,j]的雙向邊,這樣如果i不選(不妨假設),那麼久要講j->i的這一條2*e[i,j]的邊也變成割,否則i和s聯通,j和t聯通就矛盾了,這樣就使得i,j中選擇乙個僱傭的損失變為了e[i,j]就可以了。

因此,總的建圖如下:

1.從s到任意點i連一條容量為σ(j=1,n)e[i,j]的邊;

2.任意兩點i,j間連一條容量為2*e[i,j]的雙向邊;

3.任意點i到t連一條邊,容量為僱傭的費用;

ac**如下(發現當前弧優化好快9000+ms直接變成6000-ms了):

#include#include#include#define ll long long

#define n 2005

#define m 4000005

using namespace std;

int n,tot=1,d[n],h[n],fst[n],cur[n],pnt[m],nxt[m]; ll s[n],len[m],inf=(ll)100000000*(ll)100000000;

void add(int aa,int bb,ll cc)

bool bfs(int sta,int gol){

memcpy(cur,fst,sizeof(fst));

memset(d,-1,sizeof(d)); d[sta]=1;

int head=0,tail=1; h[1]=sta;

while (head

by lych

2016.1.24

BZOJ2039 employ人員僱傭

time limit 20 sec memory limit 259 mb submit 1681 solved 817 submit status discuss 作為乙個富有經營頭腦的富翁,小l決定從本國最優秀的經理中僱傭一些來經營自己的公司。這些經理相互之間合作有乙個貢獻指數,我們用ei,j表...

codevs 騎馬修柵欄 2039

題目描述 description farmer john每年有很多柵欄要修理。他總是騎著馬穿過每乙個柵欄並修復它破損的地方。john是乙個與其他農民一樣懶的人。他討厭騎馬,因此從來不兩次經過乙個柵欄。你必須編乙個程式,讀入柵欄網路的描述,並計算出一條修柵欄的路徑,使每個柵欄都恰好被經過一次。john...

COGS 2039 樹的統計

輸入檔案 counttree.in輸出檔案 counttree.out簡單對比 時間限制 1 s 記憶體限制 128 mb 關於樹的統計問題有多種多樣的版本,這裡你需要解決乙個比較簡單的問題 對於一棵包含n個節點的有根樹,將所有點從1到n編號後,對於每乙個節點v,統計出以v為根的子樹中有多少個點的編...