【计算几何】【二分图判定】Gym

题意:有n个水井,每个水井发出一些管线(都是线段),然后每条管线上最多只有一个水井。所有从不同的水井发出的管线的相交点都是清洁点(不存在清洁点是大于两条管线点的交点)。你需要在某些管线上放出一些机器人,它们会清洁所有该条管线上的清洁点。但是两条相交的管线不能同时放有机器人。问你是否存在一种可行的放机器人的方案。

将管线当成点,清洁点当作边(需要计算几何判断线段规范相交,具体看代码),建图,看看是否是二分图即可。

因为二分图显然可以选择一些点,使得每条边恰好被选择一个点(只选择X部或者只选择Y部的点就是一个合法解)。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
struct Point{
	ll x,y;
	Point(const ll &x,const ll &y){
		this->x=x;
		this->y=y;
	}
	Point(){}
	void read(){
		scanf("%I64d%I64d",&x,&y);
	}
}wells[1005];
typedef Point Vector;
Vector operator - (const Point &a,const Point &b){
	return Vector(a.x-b.x,a.y-b.y);
}
ll Cross(const Vector &a,const Vector &b){
	return a.x*b.y-a.y*b.x;
}
bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2)
{
	double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1),
	c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1);
	return c1*c2<=0 && c3*c4<=0;
}
int n,m;
struct PIPE{
	int wid;
	Point End;
	PIPE(const int &wid,const Point &End){
		this->wid=wid;
		this->End=End;
	}
	PIPE(){}
	PIPE(const int &wid,const ll &x,const ll &y){
		this->wid=wid;
		End.x=x;
		End.y=y;
	}
	void read(){
		scanf("%d",&wid);
		End.read();
	}
}pipes[1005];
bool cmp(const PIPE &a,const PIPE &b){
	return a.wid<b.wid;
}
int v[2000005],first[1005],e,next[2000005];
void AddEdge(int U,int V){
	v[++e]=V;
	next[e]=first[U];
	first[U]=e;
}
int col[1005];
bool dfs(int U,bool now)
{
	for(int i=first[U];i;i=next[i]){
		if(col[v[i]]==-1){
			col[v[i]]=(now^1);
			if(!dfs(v[i],now^1)){
				return 0;
			}
		}
		else if(col[v[i]]==col[U]){
			return 0;
		}
	}
	return 1;
}
int main(){
//	freopen("c.in","r",stdin);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i){
		wells[i].read();
	}
	for(int i=1;i<=m;++i){
		pipes[i].read();
	}
	sort(pipes+1,pipes+m+1,cmp);
	int sta;
	for(int i=1;i<=m;++i){
		if(pipes[i].wid!=pipes[i-1].wid){
			sta=i;
		}
		if(pipes[i].wid!=pipes[i+1].wid){
			for(int j=sta;j<=i;++j){
				for(int k=i+1;k<=m;++k){
					if(SegmentProperIntersection(wells[pipes[j].wid],pipes[j].End,wells[pipes[k].wid],pipes[k].End)){
						AddEdge(j,k);
						AddEdge(k,j);
					}
				}
			}
		}
	}
	memset(col,-1,sizeof(col));
	for(int i=1;i<=m;++i){
		if(col[i]==-1){
			col[i]=0;
			if(!dfs(i,0)){
				puts("impossible");
				return 0;
			}
		}
	}
	puts("possible");
	return 0;
}
原文地址:https://www.cnblogs.com/autsky-jadek/p/7700403.html