御坂网络(枚举基准,二分图)

现在有n个A点,m个B点(n,m<=200),和最大半径rmax。可以选定一个半径r<rmax,以r为半径,A点或B点为圆心,同时保证A点构造出的圆和B点构造出的圆不相交。问最大面积和。

首先ckr大佬考场上写三分,其实是不对的,但结果把数据卡过去了qwq,orz。

那正解是什么呢?首先有一个显然的性质:可能作为答案的半径一定会使得一些类别不同的圆相切,不然还可以扩张半径直到相切为止,并且圆的个数仍然不变。也有可能半径就是rmax。

所以首先要枚举半径。正常人可能都会认为,半径作自变量,最大面积和作因变量,这个函数是一个凸函数,但其实不是的,因此不能三分。枚举完半径,剩下的工作就是找到最大独立集,这个可以通过网络流跑二分图实现。

枚举半径是\(O(n^2)\)的,dinic跑二分图是\(的O(n^2m)的\),那岂不是\(O(n^6)\)了吗?具体分析一下,如果将半径从小到大排序,那么就只有加边操作,也就是说网络流不用完全重新跑,只要更新一下就行了。每次枚举半径都要至少bfs一次,因此bfs的总时间复杂度是\(O(n^4)\)。由于最多会增广n次,并且每bfs一遍就至少dfs一遍,因此dfs的总时间复杂度也是\(O(n^4)\)。

但是\(O(n^4)\)也过不了啊。观察一波方法,我们可以发现时间复杂度主要用在了判断源点和汇点的连通性上。如果我们能提前判断好S和T是否联通,那么最多只会进行n次bfs,时间复杂度就被降到\(O(n^3)\)了。因此我们不用bfs判断连通性而是用bitset传递闭包来做。如果当前只是加边,那么只需要更新与当前点相连点的传递闭包即可,时间复杂度是\(O(n^2)*O(n^2/32)=O(n^4/32)\)。如果在bfs更新了网络流,那就必须跑一遍全新的传递闭包,时间复杂度依然是\(O(n)*O(n^3/32)=O(n^4/32)\)(O记号这样用其实是不严谨的,不过理解万岁)。因此我们就达到了\(O(n^4/32)\)的复杂度。

做完这道题我的收获很大啊。虽然用了整整一天,但是我学到了二分图网络流+bitset传递闭包,就是后面半天耗费了太多时间在一个感叹号上qwq。

#include <bitset>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;const int maxn=205*2, INF=1e9;
const double PI=3.1415926535898;
double sqr(double x){ return x*x; }struct Edge{int to, next, cap;
}e[maxn*maxn];
bitset<maxn> f[maxn];  //连通性
int fir[maxn], cnte, src, dst;
void addedge(int x, int y, int v){Edge &ed=e[++cnte];ed.to=y; ed.next=fir[x]; ed.cap=v; fir[x]=cnte;if (!v) return;f[x]|=f[y];for (int i=src; i<=dst; ++i)if (f[i][x]) f[i]|=f[x];
}int dep[maxn], q[maxn], cur[maxn];int bfs(){int head=0, tail=0;memset(dep, 0, sizeof(dep)); memset(cur, 0, sizeof(cur));dep[src]=1; q[tail++]=src; int tmp;while (head<tail){tmp=q[head++];for (int i=fir[tmp]; i; i=e[i].next)if (e[i].cap>0&&!dep[e[i].to]){dep[e[i].to]=dep[tmp]+1;q[tail++]=e[i].to;}}return dep[dst]?1:0;
}int dfs(int now, int flow){if (now==dst) return flow;if (cur[now]==-1) return 0;for (int i=(cur[now]?cur[now]:fir[now]); i; i=e[i].next){cur[now]=i;if (dep[e[i].to]==dep[now]+1&&e[i].cap){int minm=dfs(e[i].to, min(flow, e[i].cap));if (minm>0){e[i].cap-=minm; e[(i-1^1)+1].cap+=minm;return minm;}}} cur[now]=-1;return 0;
}int n, m, x[maxn], y[maxn], totc, maxr;
struct Couple{int x, y, d;
}c[maxn*maxn];  //表示所有可能的半径(存的是直径的平方),同时可以用用来加边
bool cmp(const Couple &a, const Couple &b){ return a.d<b.d; }double ans;inline void update(){for (int i=src; i<=dst; ++i){f[i].reset();for (int j=fir[i]; j; j=e[j].next)if (e[j].cap) f[i][e[j].to]=1;}for (int i=src; i<=dst; ++i)for (int j=src; j<=dst; ++j)if (f[i][j]) f[i]|=f[j];
}int main(){scanf("%d%d%d", &n, &m, &maxr); src=0, dst=n+m+1;for (int i=src; i<=dst; ++i) f[i][i]=1;for (int i=1; i<=n; ++i){ addedge(0, i, 1); addedge(i, 0, 0); }for (int i=n+1; i<=n+m; ++i){ addedge(i, dst, 1); addedge(dst, i, 0); }for (int i=1; i<=n; ++i) scanf("%d", &x[i]);for (int i=1; i<=n; ++i) scanf("%d", &y[i]);for (int i=n+1; i<=n+m; ++i) scanf("%d", &x[i]);for (int i=n+1; i<=n+m; ++i) scanf("%d", &y[i]);for (int i=1; i<=n; ++i)for (int j=n+1; j<=n+m; ++j){c[++totc].x=i; c[totc].y=j;c[totc].d=sqr(x[j]-x[i])+sqr(y[j]-y[i]);if (c[totc].d>=maxr*maxr*4){ --totc; continue; }}sort(c+1, c+totc+1, cmp); int t, tot=n+m;for (int i=1; i<=totc; ++i){if (i==1||c[i].d!=c[i-1].d){  //不要统计多种情况if (f[src][dst]){ //如果源汇不联通就说明找无可找,不用更新最大独立集大小while (bfs()) while (t=dfs(src, INF)) tot-=t;update(); }ans=max(ans, tot*PI*c[i].d/4);  //记录当前枚举的半径的圆面积*最大独立集中点的个数}addedge(c[i].x, c[i].y, 1);  //后面半径继续扩大,这个半径就是非法的了。addedge(c[i].y, c[i].x, 0);}while (bfs()) while (t=dfs(src, INF)) tot-=t;  //半径扩张到rmax的话,又会有之前的半径非法printf("%.4lf\n", max(ans, tot*maxr*maxr*PI));  //懒得特判rmax=最后半径的情况了return 0;
}

转载于:https://www.cnblogs.com/MyNameIsPc/p/9070738.html

御坂网络(枚举基准,二分图)相关推荐

  1. Wannafly挑战赛26 御坂网络

    链接:https://ac.nowcoder.com/acm/contest/212/A 来源:牛客网 御坂网络 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语 ...

  2. 写一篇以名字叫御坂网络20002的魅魔为主角打败女勇者的小说

    御坂网络20002是一位拥有无尽力量的魅魔,他拥有强大的魔法和强大的技术,可以控制任何生物.他想要拯救世界,但是他受到了女勇者的阻碍.女勇者拥有神秘力量,并且准备挑战御坂网络20002去保护世界.御坂 ...

  3. soj115 御坂网络

    题意:平面上有n个A发射点和m个B发射点,可以选择安置相应A/B装置,装置范围是圆,自取半径(要求都相同且<=Rmax).异种要求范围不相交.求装置范围之和(不是并!). 标程: 1 #incl ...

  4. [Nowcoder] [Wannafly26A] 御坂网络 [模拟]

    [Link\frak{Link}Link] 思路简单,代码敲好就过了 不过显然代码敲好不是我能够轻松做到的事情 暴力扫出距离,到其它点距离都一样的就是了. #include<cstdio> ...

  5. 解读御坂美琴みさか的菱形打印程序——谈如何学习算法

    百度C语言吧主御坂美琴みさか的<C语言循环的小艺术>很久以前我就复制下来收藏了,不过一直没有研究.昨天Uval的AOAPC I: Beginning Algorithm Contests ...

  6. Bilibili到底有多少御坂妹?(一)

    目录 0.声明: 1.F12掘金 0.声明: 文章内涉及到的所有信息均为公开信息,所有Bilibili用户都可以通过搜索在网页中查看到,不存在隐私泄露问题. 1.F12掘金 打开Bilibili,按下 ...

  7. 御坂御坂题解(出自北航校赛) 约瑟夫环问题高效解决方案

    御坂御坂 题目如下: 由提示可定义函数f(x): f(1)=0 当x>1时有 f(x)=(f(x-1)+3)mod x 这个函数的意思是,f(x)是x个人的时候最后一个剩下的妹妹的编号 f(x+ ...

  8. 【Mskt问题的解决办法】使用御坂翻译器2.x版本遇到的常见问题及解决办法

    前言 使用本翻译器前,请仔细参照相关视频教程来学习如何使用,这样可以避免绝大部分的错误. 相关视频地址:https://space.bilibili.com/4834971 1.使用MisakaTra ...

  9. Bilibili到底有多少御坂妹?(二)

    目录 1.构造header 2.代码走起 1.构造header 为了要模仿浏览器操作,所以我们要伪造一下header(为防止恶意操作,这里不分享构造方法) 根据开发者工具里的信息,我们发现是GET请求 ...

最新文章

  1. mysql err 1349_MySQL 视图 第1349号错误解决方法
  2. Datalore:用于机器学习可视化的新Web方案!
  3. HTML 5 input placeholder 属性
  4. Spring数据分析思维课
  5. Maven的核心概念
  6. SAP注塑行业ERP系统软件的分析
  7. css3永久放大动画,CSS3 简单的方形放大动画
  8. 一次完整的渗透测试流程
  9. 微信公众号的简单常识
  10. 【MySQL】必知必会知识点
  11. Android App的设计架构:MVC,MVP,MVVM与架构经验谈
  12. word文档最上面有一条不是页眉的线
  13. eclipse导入idea项目
  14. Java如何获取当前系统时间
  15. 图书管理系统(Java语言)
  16. 爬虫:常见的HTTP错误代码及错误原因
  17. 数据可视化:绘制部分图表的核心代码实现
  18. 轩辕实验室 | 车载以太网CNN入侵检测算法
  19. 树莓派进阶之路 (038) - P2P 文件下载机
  20. 黑马在线教育数仓实战5

热门文章

  1. python中randint是什么意思_python中random.randint和random.randrange的区别详解
  2. 标准日本语第二十三课
  3. 8月17日云栖精选夜读:用户体验再掀高潮_阿里云域名领跑用户体验
  4. android 3d成像,android camera 实现3d效果
  5. 华硕服务器怎么装系统教程视频,华硕怎么安装linux系统教程视频
  6. 心电图心电轴怎么计算_心电轴度数计算表
  7. Mysql—索引③:优化篇(不仅仅是索引)
  8. 训练题库CTF题库最近在论证一个问题,到底是先有鸡还是先有蛋 (Ijm,lo 3wsdr4 6tghu7)
  9. 阿里云Ubuton开MCJava服务器_每小时不到1元,弹性计算服务按流量缴费
  10. 查找文献时找不到全文的解决方法