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-10-13 11:43:19

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

HDU1558 - Segment set 并查集 + 判断线段相交

HDU1558 - Segment set: http://acm.hdu.edu.cn/showproblem.php?pid=1558 题目大意: 输入一些线段的端点坐标,若两线段相交,则把他们合并成一个集合,输入数据里会有k,问和k线段相交的线段的数目(包括自己) 思路: 每次输入一条线段,都从头扫描一次. 找出之前输入的线段里面,所有和其相交的线段,并且合并(合并用的是线段的ID). 就是: 并查集 + 判断线段相交 代码: #include <iostream> #include &

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

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

HDU HDU1558 Segment set(并查集+判断线段相交)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1558 解题报告:首先如果两条线段有交点的话,这两条线段在一个集合内,如果a跟b在一个集合内,b跟c在一个集合内,那么a跟c在一个集合内.在一个平面上,有两种操作: P:在这个平面上添加一条线段 Q k:询问添加的第k条线段所在的那个集合有多少条线段 用并查集,然后就是要判断一下线段有没有交点.还有就是题目要求两个test之间要有空行,为此我还PE了一次. 1 #include<cstdio> 2

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 =

HDU2120【并查集判环】

Ice_cream's world I Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 600    Accepted Submission(s): 344 Problem Description ice_cream's world is a rich country, it has many fertile lands. Today,

HDU - 4514 湫湫系列故事——设计风景线(并查集判环+树形DP)

题目链接:https://vjudge.net/problem/HDU-4514 随着杭州西湖的知名度的进一步提升,园林规划专家湫湫希望设计出一条新的经典观光线路,根据老板马小腾的指示,新的风景线最好能建成环形,如果没有条件建成环形,那就建的越长越好.  现在已经勘探确定了n个位置可以用来建设,在它们之间也勘探确定了m条可以设计的路线以及他们的长度.请问是否能够建成环形的风景线?如果不能,风景线最长能够达到多少?  其中,可以兴建的路线均是双向的,他们之间的长度均大于0. Input 测试数据有

Codeforces Round #423 (Div. 2) C 思维,并查集 或 线段树 D 树构造,水

Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) C. String Reconstruction   思维,并查集 或 线段树 题意:一个字符串被删除了,但给出 n条信息,要还原出可能的字典序最小的字符串.信息有:字符串ti,ki个位置xi,表明原本的字符串在xi位置是以字符串ti开头的. tags:惨遭 fst,一开始把所有字符串都存下来,排序做的,结果爆内存了.. 方法1: 考虑并查集,对于字符串 ti,在位置xi,