思路:
当时一直都是正着想的,卡了好久。
题解是逆向思维,有人第一次走到当前最长边的端点时,这个人会输。然后删去最长边,找次长边,谁第一次走到当前次长边的端点就会输,同理类推。最后如果只剩起点没选,无论duoduo怎么选都会选到最长边的端点,会输;如果中间选到了起点,多多就可以选最长边另一个端点获胜。
代码:
#include<bits/stdc++.h>
#include<string>
using namespace std;
typedef long long ll;
const int mod=998244353;
const int inf=0x3f3f3f3f;
const int N=2e3+10;
ll x[N],y[N];
int vis[N];
struct node{
int u,v;
ll len;
}edge[4000010];
int cmp(node a,node b){
return a.len>b.len;
}
int main()
{int t;
cin>>t;
while(t--){
memset(vis,0,sizeof(vis));
int n,cnt=0;
cin>>n;
for(int i=0;i<n;i++)
cin>>x[i]>>y[i];
set<node>q;
for(int i=0;i<n;i++){
for(int j=0;j<i;j++){
ll len=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
edge[cnt].u=i,edge[cnt].v=j;
edge[cnt].len=len;
cnt++;
}
}
sort(edge,edge+cnt,cmp);
int sum=n,flag=0;
for(int i=0;i<cnt;i++){
set<int>s;
int j=i;
while(j<cnt&&edge[i].len==edge[j].len){
if(vis[edge[j].u]||vis[edge[j].v]){
j++;
continue;
}
s.insert(edge[j].u);
s.insert(edge[j].v);
j++;
}
i=j-1;
for(auto k:s)vis[k]=1;
if(vis[0]==1&&sum>1)flag=1;
sum-=s.size();
}
if(flag)
printf("YES\n");
else printf("NO\n");
}
}