C.Cleaning Pipes
题意:给出n条管道(线段),任意两个管道之间之多有一个交点,忽略一个管道头部和其他管道的交点,问能否选出一个不相交的管道集合来使得所有交点都被这些管道覆盖。
思路:将管道抽象成点,两个管道的交点抽象成边,那么问题转化成判断新建的图是否是一个二分图。
判断二分图最常用的方法就是染色法,本题当然也就可以用,然而我看dalao的代码还学了另一种方法:利用并查集判断,感觉这种方法的本质就是利用二分图不含奇环的性质(我自己yy的)。
具体做法就是将点集扩大两倍,i,j之间有边就merge(i, j + n),merge(i + n, j).最后判断一下i和i + n是否属于同一个集合。如果有一个属于同一个集合,则说明该图不是二分图。
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int MAXN = 2020;
struct P{
int x, y;
P(int _x = 0, int _y = 0) : x(_x), y(_y) {}
bool operator == (P &b)
{
return x == b.x && y == b.y;
}
}well[MAXN], L[MAXN], R[MAXN];
//计算向量p1p2与向量p1p3的叉积,若p1p3在p1p2的逆时针方向,则返回>0,顺时针方向返回<0
int mul(P p1, P p2, P p3)
{
return (p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y);
}
bool intersect(P p1,P p2,P q1,P q2)
{
//快速排斥
if(max(p1.x,p2.x)<min(q1.x,q2.x)||
max(q1.x,q2.x)<min(p1.x,p2.x)||
max(p1.y,p2.y)<min(q1.y,q2.y)||
max(q1.y,q2.y)<min(p1.y,p2.y))
retur