标签:大于 需要 turn name algorithm int ons ring ace
题意:有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
标签:大于 需要 turn name algorithm int ons ring ace
原文地址:http://www.cnblogs.com/autsky-jadek/p/7700403.html