题目大意:
  一个平面直角坐标系中有给定的$n(n\le50)$个红点和$m(m\le50)$个蓝点,每个点可以选择画一个半径为$r$(所有的$r$相同)的圆或不画。圆的半径上限为$R(R\le1000)$。且不同颜色的点所画成的圆不能相交,问所有圆面积的和最大是多少?

思路:
  枚举每一对不同颜色的点,求出所有可能的$r$,显然这样的$r$有$nm$个。
  对于不同颜色的点,若以$r$为半径画出的圆相交,则在这两个点之间连边,题目转化为最大独立集问题。有结论:最大独立集=点数-二分图最大匹配。用Dinic求最大匹配即可。
  对$r$排序,则每次只会增加新的边,只需要在原来的基础上进行增广即可。时间复杂度$O(n^4)$。

 #include<cmath>
#include<queue>
#include<vector>
#include<cstring>
#include<climits>
#include<algorithm>
class HouseProtection {
private:
static constexpr int N=,M=;
static constexpr double pi=M_PI;
using Point=std::pair<int,int>;
struct Length {
double l;
int u,v;
bool operator < (const Length &rhs) const {
return l<rhs.l;
}
};
struct Edge {
int from,to,remain,next;
};
Point a[N],b[N];
std::vector<Length> len;
std::vector<Edge> e;
int s,t,lev[M],cur[M],h[M];
double sqr(const double &x) const {
return x*x;
}
double dist(const Point &a,const Point &b) const {
return sqrt(sqr(a.first-b.first)+sqr(a.second-b.second));
}
void add_edge(const int &u,const int &v,const int &w) {
e.push_back({u,v,w,h[u]});
h[u]=e.size()-;
}
void bfs() {
memset(lev,-,sizeof lev);
lev[s]=;
std::queue<int> q;
q.push(s);
while(!q.empty()) {
const int &x=q.front();
for(register int i=h[x];~i;i=e[i].next) {
const int &y=e[i].to,&r=e[i].remain;
if(r&&!~lev[y]) {
lev[y]=lev[x]+;
q.push(y);
}
}
q.pop();
}
}
int dfs(const int &x,const int &flow) {
if(x==t) return flow;
for(int &i=cur[x];~i;i=e[i].next) {
const int &y=e[i].to;
if(e[i].remain&&lev[y]>lev[x]) {
if(int d=dfs(y,std::min(flow,e[i].remain))) {
e[i].remain-=d;
e[i^].remain+=d;
return d;
}
}
}
return ;
}
int dinic() {
int maxflow=;
for(;;) {
bfs();
if(!~lev[t]) break;
memcpy(cur,h,sizeof h);
while(int flow=dfs(s,INT_MAX)) {
maxflow+=flow;
}
}
return maxflow;
}
public:
double safetyFactor(const std::vector<int> &possibleXForBlue,const std::vector<int> &possibleYForBlue,const std::vector<int> &possibleXForRed,const std::vector<int> &possibleYForRed,const int &R) {
memset(h,-,sizeof h);
const int n=possibleXForBlue.size(),m=possibleXForRed.size();
for(register int i=;i<n;i++) {
a[i]={possibleXForBlue[i],possibleYForBlue[i]};
}
for(register int i=;i<m;i++) {
b[i]={possibleXForRed[i],possibleYForRed[i]};
}
for(register int i=;i<n;i++) {
for(register int j=;j<m;j++) {
const double dis=dist(a[i],b[j])/;
if(dis<R) len.push_back({dis,i,j});
}
}
len.push_back({(double)R,-,-});
std::sort(len.begin(),len.end());
s=n+m,t=n+m+;
for(int i=;i<n;i++) {
add_edge(s,i,);
add_edge(i,s,);
}
for(int i=;i<m;i++) {
add_edge(n+i,t,);
add_edge(t,n+i,);
}
int match=;
double ans=;
for(register auto &e:len) {
match+=dinic();
ans=std::max(ans,pi*sqr(e.l)*(n+m-match));
if(e.l<R) {
add_edge(e.u,n+e.v,);
add_edge(n+e.v,e.u,);
}
}
return ans;
}
};

最新文章

  1. iOS 之项目中遇到的问题总结
  2. Android知识——ViewHolder的作用与用法
  3. codevs 1036 商务旅行(Targin求LCA)
  4. Linux System and Performance Monitoring
  5. Spring AOP报错处理 Can not set field to $Proxy 在spring中使用事物或AOP遇到的错误
  6. APP性能分析1
  7. 分享我常用的一些JS验证和函数
  8. UESTC 1854
  9. 十六进制字符串转化成字符串输出HexToStr(Delphi版、C#版)
  10. 【Linux】设定一个能输入中文的英文环境!
  11. 1034: [ZJOI2008]泡泡堂BNB - BZOJ
  12. (2/18)重学Standford_iOS7开发_Xcode_课程笔记
  13. MySQL 基础 之 语句执行顺序
  14. PHP - 创建一个类
  15. Android中使用JNI获得APK签名的哈希值
  16. 记录js new Date日期处理的一个坑
  17. 从零开始学 Web 之 Vue.js(四)Vue的Ajax请求和跨域
  18. element ui表格相同内容自动合并
  19. Oracle中nvl()、instr()、及执行多条sql事务操作
  20. Linux Mint安装Docker踩坑指南

热门文章

  1. HDU1151:Air Raid(最小边覆盖)
  2. 在xml文件中引入带有@Configuration的Java类
  3. oralce的客户端sqlplus
  4. 【Foreign】冒泡排序 [暴力]
  5. [bzoj3597][scoi2014]方伯伯运椰子——分数规划,负环
  6. WC后记
  7. bzoj 1588 裸平衡树
  8. C# ICSharpCode.SharpZipLib.Zip 的使用
  9. 关于jQuery.extend
  10. bzoj 4569 [Scoi2016]萌萌哒 并查集 + ST表