题目链接
题意
在
二
维
坐
标
上
,
有
n
个
点
,
起
点
固
定
,
双
方
轮
流
选
择
一
个
未
被
经
过
的
点
,
且
要
保
证
距
离
严
格
递
增
,
问
谁
会
w
i
n
?
在二维坐标上,有n个点,起点固定,双方轮流选择一个\\未被经过的点,且要保证距离严格递增,问谁会win?
在二维坐标上,有n个点,起点固定,双方轮流选择一个未被经过的点,且要保证距离严格递增,问谁会win?
思路
比
赛
时
想
破
头
皮
都
不
知
道
要
怎
么
处
理
,
一
直
想
把
它
转
化
成
N
i
m
游
戏
,
可
惜
失
败
了
!
比赛时想破头皮都不知道要怎么处理,一直想把它转化成Nim\\游戏,可惜失败了!
比赛时想破头皮都不知道要怎么处理,一直想把它转化成Nim游戏,可惜失败了!
看
了
正
解
,
恍
然
大
悟
,
真
妙
。
原
来
这
个
游
戏
有
一
坨
必
胜
点
,
且
最
多
只
有
一
个
必
败
点
。
这
样
的
话
,
要
是
第
一
个
点
是
必
胜
点
,
肯
定
先
手
w
i
n
,
要
是
第
一
个
点
是
必
败
点
,
那
么
不
管
先
手
怎
么
走
,
后
手
都
都
会
位
于
必
胜
点
,
所
以
后
手
w
i
n
涨
知
识
了
,
以
后
确
实
可
以
往
这
个
地
方
想
,
并
尝
试
构
造
看了正解,恍然大悟,真妙。原来这个游戏有一坨必胜点,且\\最多只有一个必败点。这样的话,要是第一个点是必胜点,肯定\\先手win,要是第一个点是必败点,那么不管先手怎么走,后手都\\都会位于必胜点,所以后手win\\涨知识了,以后确实可以往这个地方想,\\并尝试构造
看了正解,恍然大悟,真妙。原来这个游戏有一坨必胜点,且最多只有一个必败点。这样的话,要是第一个点是必胜点,肯定先手win,要是第一个点是必败点,那么不管先手怎么走,后手都都会位于必胜点,所以后手win涨知识了,以后确实可以往这个地方想,并尝试构造
如
何
证
明
并
且
找
出
这
些
必
胜
点
呢
?
如何证明并且找出这些必胜点呢?
如何证明并且找出这些必胜点呢?
首
先
对
于
所
有
点
集
,
记
S
1
=
{
(
u
,
v
)
∣
d
i
s
(
u
,
v
)
最
大
}
首先对于所有点集,记S_1=\{ (u,v)|dis(u,v)最大 \}
首先对于所有点集,记S1={(u,v)∣dis(u,v)最大}
考
虑
S
1
中
点
对
(
u
,
v
)
,
显
然
可
以
推
出
u
和
v
为
必
胜
态
为
什
么
?
当
前
先
手
到
达
u
,
那
么
他
可
以
把
u
进
行
转
移
到
v
那
么
后
手
无
路
可
走
,
所
以
先
手
必
胜
考虑S_1中点对(u,v),显然可以推出u和v为必胜态\\为什么?当前先手到达u,那么他可以把u进行转移到v\\那么后手无路可走,所以先手必胜
考虑S1中点对(u,v),显然可以推出u和v为必胜态为什么?当前先手到达u,那么他可以把u进行转移到v那么后手无路可走,所以先手必胜
结
论
1
:
S
1
点
对
中
出
现
的
点
一
定
为
必
胜
状
态
结论1:S_1点对中出现的点一定为必胜状态
结论1:S1点对中出现的点一定为必胜状态
那
么
剩
下
的
点
是
什
么
状
态
呢
?
那么剩下的点是什么状态呢?
那么剩下的点是什么状态呢?
考
虑
把
S
1
点
对
中
出
现
的
点
删
掉
,
同
样
的
子
问
题
考虑把S_1点对中出现的点删掉,同样的子问题
考虑把S1点对中出现的点删掉,同样的子问题
记
S
2
=
{
(
u
′
,
v
′
)
∣
d
i
s
(
u
′
,
v
′
)
最
大
}
记S_2=\{ (u',v')|dis(u',v')最大 \}
记S2={(u′,v′)∣dis(u′,v′)最大}
考
虑
S
2
中
点
对
(
u
′
,
v
′
)
,
显
然
可
以
推
出
u
′
和
v
′
为
必
胜
态
为
什
么
?
当
前
先
手
到
达
u
′
,
那
么
他
可
以
把
u
′
进
行
转
移
到
v
′
那
么
后
手
无
路
可
走
或
者
走
到
S
1
中
的
点
(
P
a
y
−
A
t
t
e
n
t
i
o
n
)
考虑S_2中点对(u',v'),显然可以推出u'和v'为必胜态\\为什么?当前先手到达u',那么他可以把u'进行转移到v'\\那么后手无路可走或者走到S_1中的点(Pay -Attention)
考虑S2中点对(u′,v′),显然可以推出u′和v′为必胜态为什么?当前先手到达u′,那么他可以把u′进行转移到v′那么后手无路可走或者走到S1中的点(Pay−Attention)
如
果
后
手
无
路
可
走
,
那
么
先
手
必
胜
如果后手无路可走,那么先手必胜
如果后手无路可走,那么先手必胜
如
果
后
手
走
到
S
1
中
的
点
,
那
么
先
手
走
到
必
胜
状
态
点
,
从
而
推
出
先
手
必
胜
如果后手走到S_1中的点,那么先手走到必胜状态点,从而推出\\先手必胜
如果后手走到S1中的点,那么先手走到必胜状态点,从而推出先手必胜
结
论
2
:
S
2
点
对
中
出
现
的
点
一
定
为
必
胜
状
态
结论2:S_2点对中出现的点一定为必胜状态
结论2:S2点对中出现的点一定为必胜状态
推
论
:
S
i
中
的
点
一
定
为
必
胜
状
态
推论:S_i中的点一定为必胜状态
推论:Si中的点一定为必胜状态
如何写代码呢?
我
们
可
以
使
用
一
个
结
构
体
,
定
义
边
,
记
录
边
的
端
点
以
及
距
离
我们可以使用一个结构体,定义边,记录边的端点以及距离
我们可以使用一个结构体,定义边,记录边的端点以及距离
肯
定
需
要
把
所
有
边
进
行
一
个
降
序
,
然
后
对
于
一
段
相
等
d
i
s
,
进
行
分
段
,
然
后
进
行
处
理
。
肯定需要把所有边进行一个降序,然后对于一段相等dis,\\进行分段,然后进行处理。
肯定需要把所有边进行一个降序,然后对于一段相等dis,进行分段,然后进行处理。
如
何
进
行
删
点
操
作
呢
?
如何进行删点操作呢?
如何进行删点操作呢?
v
i
s
[
i
]
表
示
i
点
在
S
v
i
s
[
i
]
集
合
中
,
倘
若
我
们
正
在
考
虑
S
j
,
对
于
每
一
条
边
,
我
们
考
虑
其
端
点
,
如
果
端
点
的
v
i
s
<
j
则
表
明
该
点
已
经
删
除
则
不
需
要
考
虑
这
条
边
。
vis[i]表示i点在S_{vis[i]}集合中,倘若我们正在考虑S_j,对于每一条\\边,我们考虑其端点,如果端点的vis<j则表明该点已经删除\\则不需要考虑这条边。
vis[i]表示i点在Svis[i]集合中,倘若我们正在考虑Sj,对于每一条边,我们考虑其端点,如果端点的vis<j则表明该点已经删除则不需要考虑这条边。
详情可见代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2500;
const int maxm = 5e6 + 10;
int n, tot;
struct edge{
int u, v;
ll dis;
bool operator < (const edge &a)const{
return dis > a.dis;
}
}e[maxm];
int vis[maxn], dfn;
pair<int, int> p[maxn];
void init(){
for(int i = 1; i <= n; i++){
vis[i] = 0;
}
dfn = 0;
tot = 0;
}
void print(){
for(int i = 1; i <= tot; i++){
printf("%d---%lld----%d\n", e[i].u, e[i].dis, e[i].v);
}
}
int main(){
int t;
scanf("%d", &t);
while(t--){
scanf("%d", &n);
init();
for(int i = 1; i <= n; i++){
scanf("%d%d", &p[i].first, &p[i].second);
}
for(int i = 1; i <= n; i++){
for(int j = i + 1; j <= n; j++){
e[++tot] = (edge){i, j, (ll)1 * (p[i].first - p[j].first) * (p[i].first - p[j].first) + (ll)1 * (p[i].second - p[j].second) * (p[i].second - p[j].second)};
}
}
sort(e + 1, e + tot + 1);
//print();
ll tmp = -1;
for(int i = 1; i <= tot; i++){
int u, v; u = e[i].u; v = e[i].v;
if(tmp != e[i].dis){
dfn++;
}///新的点对距离
if((!vis[u] || vis[u] == dfn) && (!vis[v] || vis[v] == dfn)){
vis[u] = vis[v] = dfn;
}
}
if(vis[1]){
puts("YES");
}
else{
puts("NO");
}
}
return 0;
}