题目链接

https://codeforces.com/gym/101221/

题解

又是一道看了题解的作业题。
这是一个最大团(或者补图上的最大独立集)问题,而二分图最大独立集是可以做的,因此可以考虑转化成二分图。
枚举点集的直径的两端点 \(x,y\),满足 \(dis(x,y)\le d\),那么剩下点的可选范围就是两个分别以 \(x,y\) 为圆心、\(dis(x,y)\) 为半径的圆的交。

可以发现,以两点连线为界,交的区域被分成了两部分。如果两个点距离大于 \(dis(x,y)\),那么它们一定位于不同的两部分。
于是天然的二分图就构建好了!在上面求最大独立集也就是用总点数减去最大匹配即可。
时间复杂度 \(O(n^{4.5})\),但是跑得飞快,cf 上只用 \(46\text{ms}\).
另外 lk 的博客上说是 \(O(n^4)\),但并不知道为什么。

代码

#include<bits/stdc++.h>
#define llong long long
#define mkpr make_pair
#define x first
#define y second
#define iter iterator
#define riter reverse_iterator
#define y1 Lorem_ipsum_
#define tm dolor_sit_amet_
using namespace std;inline int read()
{int x = 0,f = 1; char ch = getchar();for(;!isdigit(ch);ch=getchar()) {if(ch=='-') f = -1;}for(; isdigit(ch);ch=getchar()) {x = x*10+ch-48;}return x*f;
}namespace NetFlow
{const int N = 202;const int M = 10200;const int INF = 1e6;struct Edge{int v,w,nxt;} e[(M<<1)+3];int fe[N+3];int te[N+3];int dep[N+3];int que[N+3];int n,en,s,t;void clear(){for(int i=1; i<=n; i++) fe[i] = te[i] = dep[i] = que[i] = 0;for(int i=1; i<=en; i++) e[i].v = e[i].w = e[i].nxt = 0;n = s = t = 0; en = 1;}void addedge(int u,int v,int w){
//      printf("addedge %d %d %d\n",u,v,w);en++; e[en].v = v; e[en].w = w;e[en].nxt = fe[u]; fe[u] = en;en++; e[en].v = u; e[en].w = 0;e[en].nxt = fe[v]; fe[v] = en;}bool bfs(){for(int i=1; i<=n; i++) dep[i] = 0;int head = 1,tail = 1; que[1] = s; dep[s] = 1;while(head<=tail){int u = que[head]; head++;for(int i=fe[u]; i; i=e[i].nxt){int v = e[i].v;if(e[i].w>0 && dep[v]==0){dep[v] = dep[u]+1;if(v==t) return true;tail++; que[tail] = v;}}}return false;}int dfs(int u,int cur){if(u==t||cur==0) {return cur;}int rst = cur;for(int &i=te[u]; i; i=e[i].nxt){int v = e[i].v;if(e[i].w>0 && rst>0 && dep[v]==dep[u]+1){int flow = dfs(v,min(rst,e[i].w));if(flow>0){e[i].w -= flow;    rst -= flow;e[i^1].w += flow;if(rst==0) {return cur;}}}}if(rst==cur) {dep[u] = -2;}return cur-rst;}int dinic(int _n,int _s,int _t){n = _n,s = _s,t = _t;int ret = 0;while(bfs()){for(int i=1; i<=n; i++) te[i] = fe[i];memcpy(te,fe,sizeof(int)*(n+1));ret += dfs(s,INF);}return ret;}void dfs2(int u){dep[u] = 1;for(int i=fe[u]; i; i=e[i].nxt) if(e[i].w>0){int v = e[i].v; if(dep[v]) continue;dfs2(v);}}void calcway(){for(int i=1; i<=n; i++) dep[i] = 0;dfs2(1);}
}
using NetFlow::addedge;
using NetFlow::dinic;const int mxN = 100;
struct Point {int x,y;};
typedef Point Vector;
Point operator +(Point x,Point y) {return (Point){x.x+y.x,x.y+y.y};}
Point operator -(Point x,Point y) {return (Point){x.x-y.x,x.y-y.y};}
int Norm2(Vector x) {return x.x*x.x+x.y*x.y;}
int Cross(Vector x,Vector y) {return x.x*y.y-x.y*y.x;}Point a[mxN+3]; vector<int> way;
int n; int d;int main()
{n = read(),d = read();for(int i=1; i<=n; i++) {a[i].x = read(),a[i].y = read();}int ans = 1; way.push_back(1);for(int x=1; x<=n; x++) for(int y=x+1; y<=n; y++) if(Norm2(a[x]-a[y])<=d*d){vector<int> s1,s2; int cd = Norm2(a[x]-a[y]);for(int i=1; i<=n; i++) if(i!=x&&i!=y&&Norm2(a[i]-a[x])<=cd&&Norm2(a[i]-a[y])<=cd){if(Cross(a[y]-a[x],a[i]-a[x])>=0) {s1.push_back(i);} else {s2.push_back(i);}}NetFlow::clear();for(int i=0; i<s1.size(); i++) addedge(1,i+3,1);for(int i=0; i<s2.size(); i++) addedge(i+s1.size()+3,2,1);for(int i=0; i<s1.size(); i++) for(int j=0; j<s2.size(); j++){if(Norm2(a[s2[j]]-a[s1[i]])>cd) {addedge(i+3,j+s1.size()+3,1);}}int cur = s1.size()+s2.size()-dinic(s1.size()+s2.size()+2,1,2)+2;if(cur>ans){ans = cur; way.clear(); way.push_back(x),way.push_back(y);NetFlow::calcway();for(int i=0; i<s1.size(); i++) if(NetFlow::dep[i+3]) {way.push_back(s1[i]);}for(int i=0; i<s2.size(); i++) if(!NetFlow::dep[i+s1.size()+3]) {way.push_back(s2[i]);}}}printf("%d\n",ans);for(int i=0; i<way.size(); i++) printf("%d ",way[i]); puts("");return 0;
}

Gym 101221I [WF2014]Sensor Network (二分图匹配)相关推荐

  1. 【bzoj4080】[Wf2014]Sensor Network 随机化

    题目描述 魔法炮来到了帝都,除了吃特色菜之外,还准备去尝一尝著名的北京烤鸭.帝都一共有n(1<=1<=100)个烤鸭店,可以看成是二维平面内的点.不过由于魔法炮在吃烤鸭之前没有带钱,所以吃 ...

  2. 「LibreOJ Round #11」Misaka Network 与测试 (网络流跑二分图匹配)

    description 研究者们想要测试 Misaka Network,于是他们把 Misaka Network 中的所有妹妹们召集到了一起. 现在妹妹们排成了 N行 M 列,有的位置没有人.现在研究 ...

  3. Dinic二分图匹配 || Luogu P3386

    题面:[模板]二分图匹配 思路:Dinic实现二分图匹配,要建一个超级源点(S)和超级汇点(T),分别定为N+M+1和N+M+2 然后S去和N中的数建正边和反边,正边权值为1,反边权值为0:M中的数去 ...

  4. 二分图匹配匈牙利算法DFS实现

    1 /*==================================================*\ 2 | 二分图匹配(匈牙利算法DFS 实现) 3 | INIT: g[][]邻接矩阵; ...

  5. poj1274(二分图匹配)

    (一道基础的二分图匹配) 题目意思大概为N个牛和M个栅栏,一个牛和一个栅栏只能匹配一次,求最大匹配 直接套用二分图最大匹配模板即可 #include <iostream> #include ...

  6. poj2724(二分图匹配)

    题目大概意思为有部分奶酪需要处理,若两个奶酪的二进制只有一位不同,则可以一起处理,问最少需要处理几次 题目思路: 将可以一起处理的两个奶酪用边连接在一起,相当于边只连接二进制中有偶数个1的奶酪和二进制 ...

  7. 算法模板——二分图匹配

    实现功能为二分图匹配 原理:匈牙利算法,核心思想--匹配上了就配,没直接匹配上也要通过前面的腾出位置让这个匹配上(详见:趣写算法系列之--匈牙利算法) 本程序以Codevs2776为例 详见Codev ...

  8. 算法:ACM二分图匹配 HDU2063

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2063 摘录于互联网,原创作者redraiment,很详细的二分图匹配入门资料! 2063 过山车 Pr ...

  9. BZOJ1433 [ZJOI2009]假期的宿舍 - 二分图匹配

    题解 一道裸的二分图匹配,稍微有一点细节需要注意, 但是非常裸= = 本校并且住校的向自己的床和 自己认识的并且本校的人的床连边 离校的不需要向外连边 不是本校的就和自己认识的 并且是本校的人的床连边 ...

最新文章

  1. Hubble.net 简介及与Lucene.net 对比测试
  2. shell编程【分发系统】
  3. 2019,一线程序员该如何面对中年危机?
  4. hexo的yelee主题修改左上角的博客名字颜色、修改代码模块中的引号内部的字体颜色
  5. mysql 5.5.41 下载_MySQL 5.5.41/5.6.22 发布下载
  6. DNS的A、CNAME、MX、NS、TXT、SPF记录
  7. 部署WEB项目到服务器(三)安装mysql到linux服务器(Ubuntu)详解
  8. 虚拟化网络与云网关打通的解决方案
  9. AndroidStudio_排坑指南_随时更新---Android原生开发工作笔记231
  10. 卸载loadrunner
  11. HALCON 21.11:深度学习笔记---分类(10)
  12. 中国各民族名称的罗马字母拼写法和代码-GBT 3304-1991
  13. Web API数据传输加密
  14. Vue:解决[Vue warn]: Failed to resolve directive: modle (found in Anonymous)
  15. Android固定帧率录屏
  16. 微信小程序之实现到商品列表跳转商品详情页
  17. Xshell的Sessions存放目录
  18. imx6ul uart8路串口调试(代码)
  19. 使用AutoFac组织多项目应用程序
  20. 如何看待:Oracle Java SE 8 发行版更新 ? --- 变向激励学习 JDK 10 吗?

热门文章

  1. “相对论“ 2019-07-10
  2. 科学前进的车轮永不停歇 2018-04-28
  3. TypeError: 'function' object is not subscriptable
  4. VTK修炼之道52:图形基本操作进阶_多分辨率策略(模型抽取的三种方法)
  5. [OS复习]操作系统综述2
  6. C#简单操作Excel
  7. Ajax里的onreadystatechange的作用
  8. HTTP VS RPC
  9. Idea中一个服务按多个端口同时启动
  10. httpbin.org的使用