題意:給定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 #includeview code#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;
}
BZOJ1497 NOI2006 最大獲利
什麼是最大權閉合子圖 先解釋一下有向圖的閉合圖 閉合圖內任意點的任意後繼也一定還在閉合圖中。物理意義 事物間依賴關係 乙個事件要發生,它需要的所有前提也都一定要發生。最大權閉合圖 點權之和最大的閉合圖 最大權閉合圖構圖方法 1.增加源s匯t 2.源s連線原圖的正權點,容量為相應點權 3.原圖的負權點...
bzoj 1497 NOI2006最大獲利
我對題意的理解 給出一堆公司和一堆使用者,我們買公司需要花錢,每個使用者會支付報酬當且僅當他所鍾愛的兩個公司我都買了,問最大獲利 最大權閉合子圖 好厲害的樣子 首先我們連邊最小割ans 答案就是sum ans 這個可以想,sum表示在不需要支出的情況下的獲利,現在我們需要支出,所以要跑一遍最小割。感...
bzoj1497 NOI2006 最大收益
最小割 思路比較簡單 點數看起來很多但是因為是類似二分圖的東西所以跑的比較快 源點對每個使用者連容量為收益的邊 使用者向中轉站連容量無窮大的邊 中轉站向匯點連容量為成本的邊 要麼割掉使用者帶來的收益 要麼割掉成本 include include include using namespace std...