【题目大意】

给你$n$个点,被一个半径为$R$的元圆划分成内(包含边界)、外两个部分。

要连若干线,每个点只能连一条线,不存在重点和三点共线。

线只能连在内部点和外部点之间,线长度不超过$d$。

如果一个外部点$w$和三个内部点$x,y,z$距离都不超过$d$,且两个内部点$x,z$没有和外部点$w$连线,我们准备从外部点$w$连到内部点$y$。那么如果$x$和$z$的连线有和$w$和$y$的连线相交,那么是不合法的。

求合法情况下,最多连多少线。以及方案。

$1 \leq n \leq 10^3, 1 \leq |x_i|, |y_i|, d, R \leq 2\times 10^4$

【题解】

考虑先把点分类。很明显发现答案=最大匹配。

对于每个外部点,以它为中心把内部点极角排序,那么得到了一个访问序列,然后我们直接跑匈牙利即可。

考虑这样如何保证那个奇怪的条件:

如果$x,y,z$按极角序顺次排过来,那么扫到$y$的时候,$x$如果没被匹配,一定先被扫描了,并当做匹配点。

所以这样保证了没有奇怪的条件这个情况。

然后我们就能求出匹配,考虑求方案。

对于匹配,需要找到一个合法的连边顺序(就保证一定要按这个极角序从前往后连边即可)

暴力找方案即可。

总复杂度$O(n^3)$,匈牙利跑不满,而且n一般来说为n/2(因为把点分成了一半)

这里极角排序可以用叉积,因为是圆外的点朝圆内的点连边,角度范围小于180°。

# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm> using namespace std; typedef long long ll;
typedef unsigned long long ull;
typedef long double ld; const int M = , N = 1e5 + ;
const int mod = ; int n, R, d;
struct P {
int x, y;
P() {}
P(int x, int y) : x(x), y(y) {}
friend P operator + (P a, P b) {
return P(a.x + b.x, a.y + b.y);
}
friend P operator - (P a, P b) {
return P(a.x - b.x, a.y - b.y);
}
friend int operator * (P a, P b) {
return a.x * b.y - a.y * b.x;
}
}a[M], b[M], C;
int an, bn; struct pa {
P a;
int id;
pa() {}
pa(P a, int id) : a(a), id(id) {}
}c[M]; int cn; P cmp_t;
int g[M][M], gn[M];
inline bool cmp(pa a, pa b) {
return (a.a - cmp_t) * (b.a - cmp_t) > ;
} inline ll dis2(P a, P b) {
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
} bool vis[M];
int from[M], to[M];
int aid[M], bid[M]; inline int hungry(int x) {
for (int i=; i<=gn[x]; ++i) {
if(!vis[g[x][i]]) {
vis[g[x][i]] = ;
if(from[g[x][i]] == || hungry(from[g[x][i]])) {
from[g[x][i]] = x;
return ;
}
}
}
return ;
} int main() {
freopen("etoile.in", "r", stdin);
freopen("etoile.out", "w", stdout);
cin >> n >> R >> d;
for (int i=, _x, _y; i<=n; ++i) {
scanf("%d%d", &_x, &_y);
if(i == ) C = P(_x, _y);
if(dis2(P(_x, _y), C) <= (ll)R * R) aid[++an] = i, a[an] = P(_x, _y);
else bid[++bn] = i, b[bn] = P(_x, _y);
} // puts("===========");
// for (int i=1; i<=an; ++i) printf("%d %d\n", a[i].x, a[i].y);
// puts("===========");
// for (int i=1; i<=bn; ++i) printf("%d %d\n", b[i].x, b[i].y);
// puts("==========="); for (int i=; i<=bn; ++i) {
cmp_t = b[i]; cn = ;
for (int j=; j<=an; ++j)
if(dis2(a[j], cmp_t) <= (ll)d * d) c[++cn] = pa(a[j], j);
sort(c+, c+cn+, cmp);
for (int j=; j<=cn; ++j) g[i][j] = c[j].id;
gn[i] = cn;
} int ans = ;
for (int i=; i<=bn; ++i) {
memset(vis, , sizeof vis);
ans += hungry(i);
} for (int i=; i<=an; ++i) to[from[i]] = i; memset(vis, , sizeof vis);
cout << (ans << ) << endl; for (int i=; i<=ans; ++i) {
bool hv = ;
for (int j=; j<=bn; ++j) {
if(!to[j]) continue;
for (int k=; k<=gn[j]; ++k) {
if(!vis[g[j][k]]) {
if(g[j][k] == to[j]) hv = ;
break;
}
}
if(hv) {
vis[to[j]] = ;
printf("%d %d\n", bid[j], aid[to[j]]);
break;
}
}
}
return ;
}
/*
10 5530 5385
8 5730
5220 61
2896 2950
1025 649
5509 1773
6057 2432
6435 975
5366 8341
1127 3616
2849 1689
*/

「6月雅礼集训 2017 Day5」仰望星空的更多相关文章

  1. 「6月雅礼集训 2017 Day5」学外语

    [题目大意] 给出$\{P_i\}$,求经过以下操作后能够得到的不同序列个数: 第一步,选择$i, j$,交换$P_i,P_j$:第二步,把所有$P_x=i$的$P_x$变为$j$,把所有$P_x=j ...

  2. 「6月雅礼集训 2017 Day5」吃干饭

    [题目大意] 询问[L,R]中选若干个数异或起来得到的答案集合大小.多组数据. 对于50%的数据,$R - L \leq 10^4$ 对于100%的数据,$R - L \leq 10^{18}, T ...

  3. 「6月雅礼集训 2017 Day10」quote

    [题目大意] 一个合法的引号序列是空串:如果引号序列合法,那么在两边加上同一个引号也合法:或是把两个合法的引号序列拼起来也是合法的. 求长度为$n$,字符集大小为$k$的合法引号序列的个数.多组数据. ...

  4. 「6月雅礼集训 2017 Day4」qyh(bzoj2687 交与并)

    原题传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2687 [题目大意] 给出若干区间,求一个区间的大于等于2的子集,使得 |区间并| 和 | ...

  5. 「6月雅礼集训 2017 Day11」delight

    [题目大意] 有$n$天,每天能吃饭.睡觉.什么事也不干 每天吃饭的愉悦值为$e_i$,睡觉的愉悦值为$s_i$,什么都不干愉悦值为0. 要求每连续$k$天都要有至少$E$天吃饭,$S$天睡觉. 求最 ...

  6. 「6月雅礼集训 2017 Day11」jump

    [题目大意] 有$n$个位置,每个位置有一个数$x_i$,代表从$i$经过1步可以到达的点在$[\max(1, i-x_i), \min(i+x_i, n)]$中. 定义$(i,j)$的距离表示从$i ...

  7. 「6月雅礼集训 2017 Day11」tree

    [题目大意] 给出一棵带权树,有两类点,一类黑点,一类白点. 求切断黑点和白点间路径的最小代价. $n \leq 10^5$ [题解] 直接最小割能过..但是树形dp明显更好写 设$f_{x,0/1/ ...

  8. 「6月雅礼集训 2017 Day10」perm(CodeForces 698F)

    [题目大意] 给出一个$n$个数的序列$\{a_n\}$,其中有些地方的数为0,要求你把这个序列填成一个1到$n$的排列,使得: $(a_i, a_j) = 1$,当且仅当$(i, j) = 1$.多 ...

  9. 「6月雅礼集训 2017 Day8」route

    [题目大意] 给出平面上$n$个点,求一条连接$n$个点的不相交的路径,使得转换的方向符合所给长度为$n-2$的字符串. $n \leq 5000$ [题解] 考虑取凸包上一点,然后如果下一个是‘R' ...

随机推荐

  1. Thrift IDL使用方式

    I.背景 众所周知,Thrift是一个RPC的框架,其可用于不同语言之间的服务相互调用.比如最近接触到的一个运用环境: *前端使用Node.Js重构了部分我们的老旧代码(前后端未分离的SpringBo ...

  2. 3DMAX贴图无法显示

    问题描述:我在点击"将材质指定给选定对象"按钮之后,模型只是变灰了,没有显示出我贴的图. 原因是:没有显示贴图. 我的解决方案:点击材质编辑器里面的"视口中显示敏感处理材 ...

  3. 3dContactPointAnnotationTool开发日志(三)

      今天的目的是把obj文件导到场景里.具体将制定路径的obj文件导进去我用的是这个方法.导进去后呈现的是一个黑色的影子.   导入后还想实现一下缩放功能,请看这个方法.缩放实现起来也很简单.   光 ...

  4. 结对作业二——WordCount进阶版

    软工作业三 要求地址 作业要求地址 结对码云项目地址 结对伙伴:秦玉 博客地址 PSP表格 PSP2.1 个人开发流程 预估耗费时间(分钟) 实际耗费时间(分钟) Planning 计划 10 7 · ...

  5. sublime text 输入法不跟随光标

    1.引子 sublime text 有个BUG,那就是不支持中文的鼠标跟随(和PS类似输入的光标和文字候选框不在一起).如下图: 2.插件 安装IMESupport插件即可插件,这款插件是日本人写的. ...

  6. (转)linux IO 内核参数调优 之 参数调节和场景分析

    1. pdflush刷新脏数据条件 (linux IO 内核参数调优 之 原理和参数介绍)上一章节讲述了IO内核调优介个重要参数参数. 总结可知cached中的脏数据满足如下几个条件中一个或者多个的时 ...

  7. [计算机网络] DNS何时使用TCP协议,何时使用UDP协议

    DNS同时占用UDP和TCP端口53是公认的,这种单个应用协议同时使用两种传输协议的情况在TCP/IP栈也算是个另类.但很少有人知道DNS分别在什么情况下使用这两种协议. 先简单介绍下TCP与UDP. ...

  8. [剑指Offer] 63.数据流中的中位数

    题目描述 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值. c ...

  9. Activiti5工作流笔记二

    流程变量 import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import org.activiti ...

  10. 【bzoj2591】[Usaco 2012 Feb]Nearby Cows 树形dp

    题目描述 Farmer John has noticed that his cows often move between nearby fields. Taking this into accoun ...