URAL - 1966 - Cycling Roads(并查集 + 判线段相交)

来源:互联网 发布:联通3g拨号软件 编辑:程序博客网 时间:2024/05/22 03:33

题意:n 个点,m 条边(1 ≤ m < n ≤ 200),问所有点是否连通(两条边相交,则该 4 点连通)。

题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1966

——>>对于每条边,边上的两端点并入集合,枚举边与边,判断他们是否相交,是的话各点并入集合,最后看集合内元素的个数是否为n。。

#include <cstdio>#include <cmath>const int MAXN = 200 + 10;const double EPS = 1e-8;struct POINT{    double x;    double y;    POINT(){}    POINT(double x, double y) : x(x), y(y){}} p[MAXN];int n, m;int fa[MAXN], cnt[MAXN];int u[MAXN], v[MAXN];typedef POINT Vector;Vector operator - (Vector A, Vector B){    return Vector(A.x - B.x, A.y - B.y);}int Dcmp(double x){    if (fabs(x) < EPS) return 0;    return x > 0 ? 1 : -1;}double Dot(Vector A, Vector B){    return A.x * B.x + A.y * B.y;}double Cross(Vector A, 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);    double c2 = Cross(a2 - a1, b2 - a1);    double c3 = Cross(b2 - b1, a1 - b1);    double c4 = Cross(b2 - b1, a2 - b1);    return Dcmp(c1) * Dcmp(c2) < 0 && Dcmp(c3) * Dcmp(c4) < 0;}bool OnSegment(POINT p, POINT a1, POINT a2){    return Dcmp(Cross(a1 - p, a2 - p)) == 0 && Dcmp(Dot(a1 - p, a2 - p)) < 0;}void Init(){    for (int i = 1; i <= n; ++i)    {        fa[i] = i;        cnt[i] = 1;    }}int Find(int x){    return x == fa[x] ? x : (fa[x] = Find(fa[x]));}void Union(int x, int y){    int xroot = Find(x);    int yroot = Find(y);    if (xroot != yroot)    {        fa[yroot] = xroot;        cnt[xroot] += cnt[yroot];    }}void Read(){    for (int i = 1; i <= n; ++i)    {        scanf("%lf%lf", &p[i].x, &p[i].y);    }    for (int i = 0; i < m; ++i)    {        scanf("%d%d", u + i, v + i);        Union(u[i], v[i]);        for (int j = 1; j <= n; ++j)        {            if (j != u[i] && j != v[i] && OnSegment(p[j], p[u[i]], p[v[i]]))            {                Union(j, u[i]);            }        }    }}void Merge(){    for (int i = 0; i < m; ++i)    {        for (int j = i + 1; j < m; ++j)        {            if (SegmentProperIntersection(p[u[i]], p[v[i]], p[u[j]], p[v[j]]))            {                Union(u[i], u[j]);            }        }    }}void Output(){    cnt[Find(1)] == n ? puts("YES") : puts("NO");}int main(){    while (scanf("%d%d", &n, &m) == 2)    {        Init();        Read();        Merge();        Output();    }    return 0;}


0 0