[BZOJ1497] [NOI2006]最大获利
Description
新的技術正沖擊著手機通訊市場,對于各大運營商來說,這既是機遇,更是挑戰。THU集團旗下的CS&T通訊公司在新一代通訊技術血戰的前夜,需要做太多的準備工作,僅就站址選擇一項,就需要完成前期市場研究、站址勘測、最優化等項目。在前期市場調查和站址勘測之后,公司得到了一共N個可以作為通訊信號中轉站的地址,而由于這些地址的地理位置差異,在不同的地方建造通訊中轉站需要投入的成本也是不一樣的,所幸在前期調查之后這些都是已知數據:建立第i個通訊中轉站需要的成本為Pi(1≤i≤N)。另外公司調查得出了所有期望中的用戶群,一共M個。關于第i個用戶群的信息概括為Ai, Bi和Ci:這些用戶會使用中轉站Ai和中轉站Bi進行通訊,公司可以獲益Ci。(1≤i≤M, 1≤Ai, Bi≤N) THU集團的CS&T公司可以有選擇的建立一些中轉站(投入成本),為一些用戶提供服務并獲得收益(獲益之和)。那么如何選擇最終建立的中轉站才能讓公司的凈獲利最大呢?(凈獲利 = 獲益之和 - 投入成本之和)
Input
輸入文件中第一行有兩個正整數N和M 。第二行中有N個整數描述每一個通訊中轉站的建立成本,依次為P1, P2, …, PN 。以下M行,第(i + 2)行的三個數Ai, Bi和Ci描述第i個用戶群的信息。所有變量的含義可以參見題目描述。
Output
你的程序只要向輸出文件輸出一個整數,表示公司可以得到的最大凈獲利。
Sample Input
5 5 1 2 3 4 5 1 2 3 2 3 4 1 3 3 1 4 2 4 5 3Sample Output
4Solution
考慮最小割模型。
對于每個基站設點\(A_i\),對每種人設點\(B_i\)。
對于每個\(A_i\)連邊\(s\to A_i\),容量為當前點費用。
對于每個\(B_i\),連邊\(B_i\to t\),容量為當前獲利。
對于每種約束,連邊\(A_i\to B_j\),容量為\(+\infty\)。
然后這個圖的最小割就是最小的損失,答案就是獲利總和減去損失。
考慮下為啥是對的,這里其實是用了一個正無窮的邊來限制一種約束,也就是說正無窮邊兩邊的邊不能同時存在。
#include<bits/stdc++.h> using namespace std;void read(int &x) {x=0;int f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f; }void print(int x) {if(x<0) putchar('-'),x=-x;if(!x) return ;print(x/10),putchar(x%10+48); } void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}const int maxn = 2e5+10; const int inf = 1e9;int n,m,s,t,ans,tot=1; int head[maxn],vis[maxn],dis[maxn]; struct edge{int to,nxt,w;}e[maxn<<1];void add(int u,int v,int w) {e[++tot]=(edge){v,head[u],w},head[u]=tot;} void ins(int u,int v,int w) {add(u,v,w),add(v,u,0);}int bfs() {memset(vis,0,(t+1)*4);memset(dis,63,(t+1)*4);queue<int > q;q.push(s),vis[s]=1,dis[s]=0;while(!q.empty()) {int now=q.front();q.pop();for(int i=head[now];i;i=e[i].nxt)if(e[i].w>0&&!vis[e[i].to]) {dis[e[i].to]=dis[now]+1;if(e[i].to==t) return 1;q.push(e[i].to),vis[e[i].to]=1;}}return 0; }int dfs(int u,int f) {if(u==t) return f;int used=0;for(int i=head[u];i;i=e[i].nxt)if(e[i].w>0&&dis[e[i].to]==dis[u]+1) {int d=dfs(e[i].to,min(e[i].w,f-used));if(d>0) e[i].w-=d,e[i^1].w+=d,used+=d;if(used==f) break;}dis[u]=-1;return used; }int dinic() {int flow=0;while(bfs()) flow+=dfs(s,inf);return flow; }int main() {read(n),read(m);s=n+m+2,t=s+1;for(int i=1,x;i<=n;i++) read(x),ins(s,i,x);for(int i=1,x,y,z;i<=m;i++) {read(x),read(y),read(z);ins(x,n+i,inf);ins(y,n+i,inf);ins(n+i,t,z);ans+=z;}write(ans-dinic());return 0; }轉載于:https://www.cnblogs.com/hbyer/p/10461622.html
總結
以上是生活随笔為你收集整理的[BZOJ1497] [NOI2006]最大获利的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小说笔名,免费起笔名474个
- 下一篇: 勤奋学习的名言警句126个