BZOJ1497 NOI2006 最大獲利 網路流

2022-10-10 21:06:17 字數 1577 閱讀 1759

題意:給定n個使用者和m個基站,每個基站有建設費用,每個使用者由(a,b,c)描述,表示a b基站都建好後能獲得c的收益,求最大獲利

題解:推薦**:胡伯濤-《最小割模型在資訊學競賽中的應用》

然後說一下我的理解,我麼按如下方式建圖:每條邊看作乙個點,然後劃分成二分圖,左邊一列是原圖中的點也就是傳送站,右邊一列是原圖中的邊抽象成的點,然後建立原點s和匯點t,s向左邊的所有點連容量為p[i]的邊,然後右邊的所有點向t連容量為c[j]的邊,如果原圖中一條邊e連線點u v(e產生收益,前提是u v均已被選擇),那麼在二分圖中將左邊的u v分別和右邊的e相連,容量為無窮大。

然後解釋為何這樣構圖,根據最小割的性質,一條無窮大的邊一定不會在最小割中,因此最小割中的邊要麼起點是s,要麼終點是v

由於:淨收益=(總收益-花費)

因此:最大淨收益=全部收益-(最小收益+最小花費)

也就是說我們要讓花費與沒有被利用的邊的邊權和的和最小(也就是建造傳送站的花費和不能產生收益的邊的收益的和最小)。

實際上我們的決策過程就是在判定每個傳送站是否需要建造。如果刪掉s出發的指向u的邊,就代表不建造u這個傳送站;同時由於割的性質,必須要刪除以u為基礎的收益的那個點連向t的邊才可以。因為建好的圖中s出發的邊代表花費,而連向t的邊代表收益,因而這樣跑出的最小割就是(最小總收益+最小花費)。說白了這就是個補集的思想,既然求不出最大的就先求最小的,然後用總的減去最小的不就是最大了的吧。

#include #include 

#include

#include

#include

#include

#include

#include

using

namespace

std;

const

int maxn=50000+2

;const

int maxm=6000000+2

;struct

edge

edge(

int _u,int

_c):u(_u),c(_c){}

}e[maxm];

intn,m,cnt,d[maxn],cur[maxn],sum;

queue

q;vector

tab[maxn];

void insert(int u,int v,int

c)bool bfs(int s,int

t)

return d[t]>0;}

int dfs(int x,int f,int

t)

if(!used) d[x]=-1

;

return

used;

}int dinic(int s,int

t)

return

ret;

}int

main()

for(int i=1,a,b,c;i<=m;i++)

printf(

"%d\n

",sum-dinic(0,n+m+1

));

return0;

}

view code

BZOJ1497 NOI2006 最大獲利

什麼是最大權閉合子圖 先解釋一下有向圖的閉合圖 閉合圖內任意點的任意後繼也一定還在閉合圖中。物理意義 事物間依賴關係 乙個事件要發生,它需要的所有前提也都一定要發生。最大權閉合圖 點權之和最大的閉合圖 最大權閉合圖構圖方法 1.增加源s匯t 2.源s連線原圖的正權點,容量為相應點權 3.原圖的負權點...

bzoj 1497 NOI2006最大獲利

我對題意的理解 給出一堆公司和一堆使用者,我們買公司需要花錢,每個使用者會支付報酬當且僅當他所鍾愛的兩個公司我都買了,問最大獲利 最大權閉合子圖 好厲害的樣子 首先我們連邊最小割ans 答案就是sum ans 這個可以想,sum表示在不需要支出的情況下的獲利,現在我們需要支出,所以要跑一遍最小割。感...

bzoj1497 NOI2006 最大收益

最小割 思路比較簡單 點數看起來很多但是因為是類似二分圖的東西所以跑的比較快 源點對每個使用者連容量為收益的邊 使用者向中轉站連容量無窮大的邊 中轉站向匯點連容量為成本的邊 要麼割掉使用者帶來的收益 要麼割掉成本 include include include using namespace std...