题面:
在平面上有n个点,第i个点的坐标为,。由题目名称可知,由于这是一道图论题,所以这n个点形成了一个无向完全图,每两个点之间都有恰好一条边。比较不同的是,边有两种颜色,黑色和白色。你每次可以询问交互库连接某两点之间边的颜色。
zzq希望你帮他选出一棵生成树,这棵生成树要满足,所有边的颜色都相同,并且边两两只在端点处交又(即组成生成树边的平面上的线段除了共端点以外都不相交)。如果有多个解。你可以任意输出一个。可以证明一定有解。
Orz zzq神仙。
神仙交互题,考场上硬把这道题做成了计算几何题,只拿了20分暴力(蒟蒻默默溜走……
正解居然如此简洁易懂,完全没有想到。首先n个点构成一个凸多边形,考虑 i 和 i+1 之间边的颜色,如果与 i 和 i-1 的不同就把 i 弹掉,再用 i-1 比较,这是因为无论最后的生成树颜色是什么这个点都可以被加入。我的代码的实现过程用到一个栈,分别记录一下每个点入栈和出栈时候的栈顶是谁,n个点都跑完之后根据栈内剩余的边的颜色决定那些被弹出去的点都与谁连边。由于每个点最多只会进一次栈,出一次栈,所以函数调用次数不会超过。
考后改AC的代码:
#include<bits/stdc++.h>
#include "gra.hpp"
#define N 100005
int sta[N],top,col[N],now,pre[N],nxt[N];
void tree(int n){
sta[++top]=1;
col[2]=query(1,2);
pre[2]=1;
sta[++top]=2;
for(int i=3;i<=n;i++){
col[i]=query(sta[top],i);
while(top>1&&col[i]!=col[sta[top]]){
nxt[sta[top]]=i;
top--;
col[i]=query(sta[top],i);
}
pre[i]=sta[top];
sta[++top]=i;
}
int fin=col[sta[top]];
for(int i=1;i<top;++i){
for(int j=sta[i]+1;j<=sta[i+1];++j)
if(col[j]==fin)report(j,pre[j]);
else report(j,nxt[j]);
}
}