1. 程式人生 > >【計算幾何】【二分圖判定】Gym - 101485C - Cleaning Pipes

【計算幾何】【二分圖判定】Gym - 101485C - Cleaning Pipes

你是 i+1 ace 機器 ble mes 方案 clu str

題意:有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;
}

【計算幾何】【二分圖判定】Gym - 101485C - Cleaning Pipes