BZOJ 1497 [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公司可以有选择的建立一些中转站(投入成本),为一些用户提供服务并获得收益(获益之和)。那么如何选择最终建立的中转站才能让公司的净获利最大呢?(净获利 = 获益之和 - 投入成本之和)
Hint
N≤5 000,M≤50 000,0≤Ci≤100,0≤Pi≤100
Solution
题意:有一些点,选择一个点需要一定代价,有一些边,如果边连接的两点都被选择了,获得一定价值,求价值最大
其实是道非常典型的最小割模型
将题意转换一下理解,假设我们已经获得了所有的边的价值,此时对于任意一条边,我们要么花费一定的代价去选择它所连的两点,要么舍弃这条边的价值
两种方法都可以视作网络流中一条割边
全局代价最小,就是求最小割,也就是最大流
重新构图,跑最大流
//感觉每次写网络流都算不清边数,无限RE= =
1 #include<bits/stdc++.h> 2 3 #define maxn 60000+5 4 #define maxm 600000+5 5 #define set(a,b) memset(a,(b),sizeof(a)) 6 #define fr(i,a,b) for(ll i=(a),_end_=(b);i<=_end_;i++) 7 #define rf(i,b,a) for(ll i=(a),_end_=(b);i>=_end_;i--) 8 #define fe(i,a,b) for(int i=first[(b)],_end_=(a);i!=_end_;i=s[i].next) 9 #define fec(i,a,b) for(int &i=cur[(b)],_end_=(a);i!=_end_;i=s[i].next) 10 11 using namespace std; 12 13 typedef long long ll; 14 15 struct sides{ 16 int u,v,c; 17 int next; 18 }s[maxm]; 19 20 queue<int> q; 21 int first[maxn],cur[maxn]; 22 int h[maxn],ind=0; 23 int sum=0,cost=0; 24 int n,m; 25 26 void add(int u,int v,int c) 27 { 28 s[ind].u=u,s[ind].v=v,s[ind].c=c; 29 s[ind].next=first[u],first[u]=ind; 30 ind++; 31 32 s[ind].u=v,s[ind].v=u,s[ind].c=0; 33 s[ind].next=first[v],first[v]=ind; 34 ind++; 35 } 36 37 bool bfs() 38 { 39 set(h,-1); 40 h[0]=1; 41 q.push(0); 42 while( !q.empty() ){ 43 int sd=q.front();q.pop(); 44 fe(i,-1,sd) 45 if( s[i].c && h[s[i].v]==-1 ){ 46 h[s[i].v]=h[sd]+1; 47 q.push(s[i].v); 48 } 49 } 50 return h[n+m+1]!=-1; 51 } 52 53 int dfs(int u,int flow) 54 { 55 if( u==n+m+1 ) return flow; 56 int w,used=0; 57 fec(i,-1,u) 58 if( s[i].c && h[s[i].v]==h[u]+1 ){ 59 w=dfs(s[i].v,min(flow-used,s[i].c)); 60 s[i].c-=w,s[i^1].c+=w; 61 used+=w; 62 if( used==flow ) 63 return flow; 64 } 65 if( !used ) h[u]=-1; 66 return used; 67 } 68 69 void dinic() 70 { 71 while( bfs() ){ 72 fr(i,0,n+m+1) 73 cur[i]=first[i]; 74 cost+=dfs(0,INT_MAX); 75 } 76 } 77 78 int main() 79 { 80 #ifndef ONLINE_JUDGE 81 freopen("1497.in","r",stdin); 82 freopen("1497.out","w",stdout); 83 #endif 84 set(first,-1); 85 cin >> n >> m ; 86 fr(i,1,n){ 87 int k; 88 cin >> k ; 89 add(0,i,k); 90 } 91 fr(i,1,m){ 92 int u,v,c; 93 cin >> u >> v >> c ; 94 add(u,n+i,INT_MAX); 95 add(v,n+i,INT_MAX); 96 add(n+i,n+m+1,c); 97 sum+=c; 98 } 99 dinic(); 100 cout << sum-cost ; 101 return 0; 102 }