BZOJ 1497 NOI2006 最大獲利

2021-08-09 20:57:32 字數 1448 閱讀 6101

/**

轉化成最大權閉合子圖,如果要滿足使用者群c,就要建立a,b站點

把使用者群看成乙個個節點,則可以把他們劃分成兩個集合,第乙個

集合是得到滿足的集合,另乙個是未得到滿足的集合,滿足的設為

s集合,未滿足設未t集合,對於乙個使用者群,如果它屬於t集合,則

會損失一些收益,對於每乙個點,如果有收益,其點權值未正值,

如果需要建站,則點權值是負值,按照胡伯濤**中所述,對於點

權是正值的點,我們與超級源點s建立關係,其值就是點的權值,如果

點權是賦值的點,與超級匯點建立聯絡,其權值是點權的絕對值,

然後點與點之間有聯絡的話,建立邊權值未inf。

對於這個題目,從源點s與每乙個使用者群建立一條邊,權值未滿足該

使用者群後所能獲得的收益,每乙個基站與超級匯點建立一條邊,其

權值為建立該基站的費用,又由於滿足該使用者群,需要建立a,b基站,

則新增該使用者群節點到a的邊其權值為inf,新增該使用者群節點到b的

邊其權值為inf。純收入 = 總利潤-成本=(所有正的點權值之和)-最小割

最終求得最小割,從s出發進行dfs,所能遍歷到得點都是屬於s的點,

使用者群屬於s則,則滿足該使用者群的基站也必然屬於s割,因為使用者

群到這兩個點的邊都是無窮大,沒有流可以阻斷權重為無窮大的邊。

只要使用者群屬於s割,則可以獲取其收益。所以我們就先假設能獲取

所有的收益最後減去使用者群屬於t割造成的損失,就是純利潤。

*/#include #include #include #include #include using namespace std;

const int maxn = 60000;

const int inf = 0x7fffffff;

struct edge edge[maxn<<3];

int cnt,level[maxn],head[maxn],cur[maxn],s,t,n,m;

void addedge(int u,int v,int w)

bool bfs() }}

if(level[t] == -1)

return false;

else

return true;

}int dfs(int u,int flow)

}if(sum == 0) level[u] = -1;

return sum;

}int dinic()

return maxflow;

}int main()

int profit = 0;

int a,b,c;

for(int i = 1; i <= m; i++)

int ans = profit - dinic();

printf("%d\n",ans);

}return 0;

}

BZOJ1497 NOI2006 最大獲利

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

bzoj 1497 NOI2006最大獲利

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

bzoj1497 NOI2006 最大收益

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