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公司可以有选择的建立一些中转站(投入成本),为一些用户提供服务并获得收益(获益之和)。那么如何选择最终建立的中转站才能让公司的净获利最大呢?(净获利 = 获益之和 - 投入成本之和)【数据规模和约定】
80%的数据中:N≤200,M≤1 000。
100%的数据中:N≤5 000,M≤50 000,0≤Ci≤100,0≤Pi≤100。
Solution
想必这道题人人都知道,最大权闭合图的模板题~
每个用户群和每个基站建议点,用户群向依赖的基站连边,显然最大权闭合图是答案
最大权闭合图?看这里
P.S.:这题要用 Dinic ,用 GAP 会被卡
Code
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fod(i,a,b) for(i=a;i>=b;i--)
#define LL long long
#define N 60000
#define M 500000
#define INF 2000000000
using namespace std;
int n,m,nt[M],lt[M],fs[M],dt[M],zs[M],f[M],st,ed,m1,h[N],d[M];
void fx()
{
zs[m1]=m1-1;
zs[m1-1]=m1;
}
void link(int x,int y,int z)
{
d[++m1]=y;
f[m1]=z;
if (fs[x]==0) fs[x]=m1;
lt[x]=nt[lt[x]]=m1;
}
void mt(int x,int y,int z)
{
link(x,y,z);
link(y,x,0);
fx();
}
bool bfs()
{
memset(h,0,sizeof(h));
int i=0,j=1,k,p,l;
dt[j]=st;
h[st]=1;
while (i<j)
{
k=dt[++i];
for(l=fs[k];l>0;l=nt[l])
{
p=d[l];
if (f[l]>0&&h[p]==0) dt[++j]=p,h[p]=h[k]+1;
}
}
return h[ed]>0;
}
int dinic(int k,int s)
{
int i,p,l=0,sl=0;
if(k==ed) return s;
for(i=fs[k];i>0;i=nt[i])
{
p=d[i];
if (f[i]>0&&h[p]==h[k]+1)
{
l=dinic(p,min(s,f[i]));
if (l>0)
{
sl+=l;
s-=l;
f[i]-=l;
f[zs[i]]+=l;
if (s==0) break;
}
}
}
if (sl==0) h[k]=-1;
return sl;
}
int main()
{
cin>>n>>m;
st=n+m+1;
ed=n+m+2;
m1=0;
int i;
fo(i,1,n)
{
int p;
scanf("%d",&p);
mt(m+i,ed,p);
}
int s=0;
fo(i,1,m)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
s+=z;
mt(st,i,z);
mt(i,x+m,INF);
mt(i,y+m,INF);
}
while (bfs())
s-=dinic(st,INF);
cout<<s;
}