题目描述
JYY创建的电信公司,垄断着整个JSOI王国的电信网络。JYY在JSOI王国里建造了很多的通信基站。目前所有的基站
都是使用2G网络系统的。而现在3G时代已经到来了,JYY在思考,要不要把一些基站升级成3G网络的呢?JSOI王国
可以被看作为一个无穷大的二维平面,JYY一共建造了N个通信基站,第i个基站的坐标是(Xi,Yi)。每个基站有一个
通信范围Ri。第i号基站会向所有到其距离不超过Ri的基站发送信息。每个基站升级到3G网络都会有一个收益Si,
这个收益可能是正数(比如基站附近有个大城市,用户很多,赚的流量费也就很多了),也可能是负数(比如基站
周围市场不佳,收益不能填补升级基站本身的投资)。此外,由于原有的使用2G网络系统的基站无法解析从升级成
3G网络系统的基站所发来的信息(但是升级之后的基站是可以解析未升级基站发来的信息的),所以,JYY必须使
得,在升级工作全部完成之后,所有使用3G网络的基站,其通信范围内的基站,也都是使用3G网络的。由于基站数
量很多,你可以帮助JYY计算一下,他通过升级基站,最多能获得的收益是多少吗?
输入
第一行一个整数N;
接下来N行,每行4个整数,Xi,Yi,Ri,Si,表示处在(Xi,Yi)的基站的通信
范围是Ri,升级可以获得的收益是Si。
数据满足任意两个基站的坐标不同。
1≤N≤500,1≤Ri≤20000,|Xi|,|Yi|,|Si|≤10^4。
输出
输出一行一个整数,表示可以获得的最大收益。
样例输入
5
0 1 7 10
0 -1 7 10
5 0 1 -15
10 0 6 10
15 1 2 -20
0 1 7 10
0 -1 7 10
5 0 1 -15
10 0 6 10
15 1 2 -20
样例输出
5
【样例说明】
我们可以将前三座基站升级成 3G 网络,以获得最佳收益。
【样例说明】
我们可以将前三座基站升级成 3G 网络,以获得最佳收益。
根据题意要求,显然就是求最大权闭合子图,将源点连向正收益的点,流量为收益;负收益点连向汇点,流量为收益的相反数。暴力枚举两个点,如果$j$在$i$的范围内,那么就将$i$向$j$连边,流量为$INF$。答案就是正收益之和$-$最小割
#include<set> #include<map> #include<queue> #include<stack> #include<cmath> #include<cstdio> #include<vector> #include<bitset> #include<cstring> #include<iostream> #include<algorithm> #define INF 1000000000 using namespace std; int head[600]; int next[600000]; int to[600000]; int val[600000]; int d[600]; int q[600]; int n; int x[600]; int y[600]; int r[600]; int s[600]; int tot=1; int ans; int S,T; void add(int x,int y,int v) { tot++; next[tot]=head[x]; head[x]=tot; to[tot]=y; val[tot]=v; tot++; next[tot]=head[y]; head[y]=tot; to[tot]=x; val[tot]=0; } bool bfs(int S,int T) { int r=0; int l=0; memset(q,0,sizeof(q)); memset(d,-1,sizeof(d)); q[r++]=S; d[S]=0; while(l<r) { int now=q[l]; for(int i=head[now];i;i=next[i]) { if(d[to[i]]==-1&&val[i]!=0) { d[to[i]]=d[now]+1; q[r++]=to[i]; } } l++; } return d[T]!=-1; } int dfs(int x,int flow) { if(x==T) { return flow; } int now_flow; int used=0; for(int i=head[x];i;i=next[i]) { if(d[to[i]]==d[x]+1&&val[i]!=0) { now_flow=dfs(to[i],min(flow-used,val[i])); val[i]-=now_flow; val[i^1]+=now_flow; used+=now_flow; if(now_flow==flow) { return flow; } } } if(used==0) { d[x]=-1; } return used; } void dinic() { while(bfs(S,T)==true) { ans-=dfs(S,0x3f3f3f); } } bool check(int i,int j) { if((y[j]-y[i])*(y[j]-y[i])+(x[j]-x[i])*(x[j]-x[i])<=r[i]*r[i]) { return true; } else { return false; } } int main() { scanf("%d",&n); S=n+1; T=S+1; for(int i=1;i<=n;i++) { scanf("%d%d%d%d",&x[i],&y[i],&r[i],&s[i]); if(s[i]>0) { ans+=s[i]; add(S,i,s[i]); } else { add(i,T,-s[i]); } } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(check(i,j)) { add(i,j,INF); } } } dinic(); printf("%d",ans); }