URAL - 1966 - Cycling Roads(并检查集合 + 判刑线相交)

意甲冠军: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;
}

版权声明:本文博主原创文章,博客,未经同意不得转载。

时间: 2024-08-26 15:07:35

URAL - 1966 - Cycling Roads(并检查集合 + 判刑线相交)的相关文章

URAL 1966 Cycling Roads 点在线段上、线段是否相交、并查集

F - Cycling Roads Description When Vova was in Shenzhen, he rented a bike and spent most of the time cycling around the city. Vova was approaching one of the city parks when he noticed the park plan hanging opposite the central entrance. The plan had

Ural 1966 Cycling Roads

================ Cycling Roads ================ Description When Vova was in Shenzhen, he rented a bike and spent most of the time cycling around the city. Vova was approaching one of the city parks when he noticed the park plan hanging opposite the

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

题意: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

BNUOJ33566 Cycling Roads(并查集+判断两线段相交)

Cycling Roads Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on Ural. Original ID: 1966 64-bit integer IO format: %lld      Java class name: (Any) Prev Submit Status Statistics Discuss Next Font Size:  +   - Type:   None Graph T

hdu1325 Is It A Tree?并检查集合

pid=1325">职务地址 试想一下,在词和话题hdu1272是一样的. 可是hdu1272的博文中我也说了.数据比較水,所以我用非并查集的方法就AC了. 可是这题的数据没那么水,要用到并查集来解.这题的盲点和重点有这么几个: 输入不是以-1 -1结束,而是以两个负数结束 须要用并查集来推断是不是仅仅有一个"根" 须要推断全部节点的入度是否大于1 本题输入的格式.也要注意一下. 能够先忽略图中的方向的.由于假设有环的话,就变成图了.若严格的依照用parent数组来保存

《算法导论》2.3-7 检查集合中是否存在两数字和为指定的X--算法和证明

习题2.3-7:设计一个算法,对于一个给定的包含n个整数的集合S和另一个给定的整数X,该算法可以在时间内确定S中是否存在两个元素,使得它们的和恰为X. 解题思路:首先应该想到的是先用一个的排序算法对S中的元素进行排序.接下来有两种处理思路,第一种思路是遍历已经排好序了的S中的所有元素a,并采用 二分查找的方法在S中查找X-a,如果能够找到,那么说明S中确实存在两个元素的和为X,算法终止.这种思路很显然是满足的限制要求的:第二种思路是我自己 想出的一个算法,这个算法也很简单,但是其正确性不是很好证

普林斯顿大学公开课 算法1-10:并检查集合-高速整合方法优化

本节介绍了高速综合优化算法. 重量的概念,每次操作的时候将重量小的部件挂在重量大的部件之下. 这样就避免了树形结构太高的问题. 下图展示了优化前后的树形结构深度的对照. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2FpcGVpY2hhbzI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" > 证明 能够证明每一个节点的深度最大为lgN. 由于

poj 2513 Colored Sticks(欧拉路径+并检查集合+特里)

题目链接:poj 2513 Colored Sticks 题目大意:有N个木棍,每根木棍两端被涂上颜色.如今给定每一个木棍两端的颜色.不同木棍之间拼接须要颜色同样的 端才干够.问最后是否能将N个木棍拼接在一起. 解题思路:欧拉通路+并查集+字典树. 欧拉通路,每一个节点的统计度,度为奇数的点不能超过2个.并查集,推断节点 是否全然联通. 字典树,映射颜色. #include <cstdio> #include <cstring> #include <string> #i

BZOJ 1015 JSOI2008 星球大战 starwar 并检查集合

标题效果:给定一个无向图.联通谋求块的数目,以及k一个点的破坏后每次:联通,块的数目 侧面和摧毁的地步全记录,我们可以做相反的. 需要注意的是该点不能算作破坏联通块 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 400400 using namespace std; struct abcd{ int to,next; }table[M];