ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1045E Ancient civilizations

2021-04-05 20:34:32  阅读:214  来源: 互联网

标签:Ancient const Vector int edges civilizations CF1045E 三角形 col


XV.CF1045E Ancient civilizations

神题。

我们先考虑如果凸包上只有三个点时的情形。

假如该三个点是同色的,我们考虑能否在该三角形内部找到一个异色点。假如能找到,我们便可以将这个大三角形拆分成三个小三角形,每个小三角形以该异色节点和凸包上两个点为顶点,这就使得小三角形的三个顶点并不同色。这样我们就可以递归到下一种情形了。假如找不到,则明显该三角形内部所有点全部同色,直接从一个点出发连接所有点即可。

下面我们考虑三个点不全同色的情形。则必定有一个少数色。我们便在三角形内部寻找有无少数色的节点。假如有的话,明显我们可以连接该少数色节点和少数色的顶点,然后继续拆分成三个小三角形继续递归处理。假如没有,就直接暴力连即可。

下面我们考虑一般情况,即凸包上不只有三个点的情形。我们考虑将该凸包拆成一段黑一段白这样交替出现的情形。假如有两段颜色相同的凸包上节点并不相邻,明显无论怎么连都会出现交叉,直接跳无解。否则:

假如凸包上只有一种颜色的点,明显可以如三角形三点同色一样,剖分成数个小三角形进行处理。否则,即凸包上不止有一种颜色的点,那么我们找到凸包上白点中最左的那一个(指按照顺/逆时针排序后白点段中最靠左的那个),连接其和所有黑点构成三角形(并非真的相连,只是指构成三角形罢了);同理,找到黑点中最靠左的那个,并连接其和所有白点构成三角形。明显此时我们便将整个大凸包拆成了无数的异色三角形,可以递归处理了。

明显在每次递归处理中,我们都要一遍扫过所有节点判断它是否在三角形内部,故总复杂度\(O(n^2)\)。

代码:

#include<bits/stdc++.h>
using namespace std;
int n,stk[1010],tp,ord[1010];
struct Vector{
	int x,y;
	Vector(int X=0,int Y=0){x=X,y=Y;}
	friend Vector operator +(const Vector &u,const Vector &v){return Vector(u.x+v.x,u.y+v.y);}
	friend Vector operator -(const Vector &u,const Vector &v){return Vector(u.x-v.x,u.y-v.y);}
	friend int operator &(const Vector &u,const Vector &v){return u.x*v.y-u.y*v.x;}//cross times
	friend int operator |(const Vector &u,const Vector &v){return u.x*v.x+u.y*v.y;}//point times
	double operator ~()const{return atan2(y,x);}
	void read(){scanf("%d%d",&x,&y);}
	void print(){printf("(%d,%d)",x,y);}
}p[1010];
bool col[1010];
vector<pair<int,int> >edges;
void solve(int u,int v,int w){
	bool minor=col[u]^col[v]^col[w];
	int MINOR;
	if(col[u]==minor)MINOR=u;
	if(col[v]==minor)MINOR=v;
	if(col[w]==minor)MINOR=w;
	for(int i=0;i<n;i++){
		if(i==u||i==v||i==w)continue;
		if(col[i]!=minor)continue;
		bool U=((p[u]-p[i])&(p[v]-p[i]))>0;
		bool V=((p[v]-p[i])&(p[w]-p[i]))>0;
		bool W=((p[w]-p[i])&(p[u]-p[i]))>0;
		if(U!=V||V!=W||W!=U)continue;
		edges.push_back(make_pair(MINOR,i));
		solve(u,v,i),solve(v,w,i),solve(w,u,i);
		return;
	}
	for(int i=0;i<n;i++){
		if(i==u||i==v||i==w)continue;
		bool U=((p[u]-p[i])&(p[v]-p[i]))>0;
		bool V=((p[v]-p[i])&(p[w]-p[i]))>0;
		bool W=((p[w]-p[i])&(p[u]-p[i]))>0;
		if(U!=V||V!=W||W!=U)continue;
		if(col[u]==col[i]){edges.push_back(make_pair(u,i));continue;}
		if(col[v]==col[i]){edges.push_back(make_pair(v,i));continue;}
		if(col[w]==col[i]){edges.push_back(make_pair(w,i));continue;}
	}
}
bool onhull[1010];
void print(){
	printf("%d\n",edges.size());
	for(auto i:edges)printf("%d %d\n",i.first,i.second);
	exit(0);
}
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++)p[i].read(),scanf("%d",&col[i]),ord[i]=i;
	sort(ord,ord+n,[](int u,int v){return p[u].x==p[v].x?p[u].y<p[v].y:p[u].x<p[v].x;});
	for(int i=1;i<n;i++)p[ord[i]]=p[ord[i]]-p[ord[0]];
	p[ord[0]]=Vector(0,0);
	sort(ord+1,ord+n,[](int u,int v){return ~p[u]<~p[v];});
	stk[tp++]=ord[0];
	for(int i=1;i<n;i++){
		while(tp>=2&&((p[ord[i]]-p[stk[tp-1]])&(p[stk[tp-1]]-p[stk[tp-2]]))>=0)tp--;
		stk[tp++]=ord[i];
	}
	for(int i=0;i<tp;i++)onhull[stk[i]]=true;
	int l=tp,r=1;
	while(r<l&&col[stk[r]]==col[stk[0]])r++;
	while(l>r&&col[stk[l-1]]==col[stk[0]])l--;
	if(r==l){
		for(int j=1;j<tp;j++)edges.push_back(make_pair(stk[j-1],stk[j]));
		for(int i=0;i<n;i++){
			if(onhull[i]||col[i]==col[stk[0]])continue;
			for(int j=0;j<tp;j++)solve(stk[j],stk[(j+1)%tp],i);
			print();
		}
		for(int i=0;i<n;i++){
			if(onhull[i])continue;
			for(int j=i+1;j<n;j++)if(!onhull[j])edges.push_back(make_pair(i,j));
			if(col[i]==col[stk[0]])edges.push_back(make_pair(i,stk[0]));
			print();
		}
	}else{
		for(int i=r;i<l;i++)if(col[stk[i]]==col[stk[0]]){puts("Impossible");return 0;}
		for(int i=(l+1)%tp;i!=r;i=(i+1)%tp)edges.push_back(make_pair(stk[(i+tp-1)%tp],stk[i]));
		for(int i=r+1;i<l;i++)edges.push_back(make_pair(stk[i-1],stk[i]));
		for(int i=(l+1)%tp;i!=r;i=(i+1)%tp)solve(stk[(i+tp-1)%tp],stk[i],stk[r]);
		for(int i=r+1;i<l;i++)solve(stk[i-1],stk[i],stk[l%tp]);
		print();
	}
	print();
	return 0;
}

标签:Ancient,const,Vector,int,edges,civilizations,CF1045E,三角形,col
来源: https://www.cnblogs.com/Troverld/p/14619354.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有