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 several marble statues marked on it. One of such statues stood right there, by the park entrance. Vova wanted to ride in the park on the bike and take photos of all statues. The park territory has multiple bidirectional cycling roads. Each cycling road starts and ends at a marble statue and can be represented as a segment on the plane. If two cycling roads share a common point, then Vova can turn on this point from one road to the other. If the statue stands right on the road, it doesn‘t interfere with the traffic in any way and can be photoed from the road.

Can Vova get to all statues in the park riding his bike along cycling roads only?

Input

The first line contains integers n and m that are the number of statues and cycling roads in the park (1 ≤ m < n ≤ 200) . Then n lines follow, each of them contains the coordinates of one statue on the park plan. The coordinates are integers, their absolute values don‘t exceed 30 000. Any two statues have distinct coordinates. Each of the following m lines contains two distinct integers from 1 to n that are the numbers of the statues that have a cycling road between them.

Output

Print “YES” if Vova can get from the park entrance to all the park statues, moving along cycling roads only, and “NO” otherwise.

Sample Input

input output
4 2
0 0
1 0
1 1
0 1
1 3
4 2
YES

题意:

  给你n点

  给你m条直线

  问你所有点是否相连

题解:

  点在线段上、线段是否相交板子来判断

  吧相连的点加入集合

  最后判断所有点是否都在一个集合里边即可

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 5e4+20, M = 1e2+10, mod = 1e9+7, inf = 1e9+1000;
typedef long long ll;
const double INF  = 1E200;
const double EP  = 1E-10;
const int  MAXV = 30000;
const double PI  = 3.14159265;
struct POINT
{
 double x;
 double y;
 POINT(double a=0, double b=0) { x=a; y=b;} //constructor
 POINT operator - (const POINT &b) const {
    return POINT(x - b.x , y - b.y);
 }
  double operator ^ (const POINT &b) const {
    return x*b.y - y*b.x;
 }
};
struct LINE
{
 POINT s;
 POINT e;
 LINE(POINT a, POINT b) { s=a; e=b;}
 LINE() { }
};
int sgn(double x) {if(fabs(x) < EP)return 0;if(x < 0) return  -1;else return 1;}
bool inter(LINE l1,LINE l2) {
    return
    max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
    max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
    max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
    max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
    sgn((l2.s-l1.e) ^ (l1.s - l1.e))*sgn((l2.e-l1.e) ^ (l1.s-l1.e)) <= 0 &&
    sgn((l1.s-l2.e) ^ (l2.s - l2.e))*sgn((l1.e-l2.e) ^ (l2.s-l2.e)) <= 0;
}
bool onseg(POINT P , LINE L) {
    return
    sgn((L.s-P)^(L.e-P)) == 0 &&
    sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0 &&
    sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0;
}
//intersection
POINT p[N];
LINE dg[N];
int n,m,posa[N],posb[N],fa[N],cnt,vis[N];

int finds(int x) {return x==fa[x]?x:fa[x]=finds(fa[x]);}
void unions(int x,int y) {
    int fx = finds(x);
    int fy = finds(y);
    if(fx != fy) fa[fx]  = fy;
}
int main()
{
    scanf("%d%d",&n,&m);

    for(int i=1;i<=n;i++) fa[i] = i;

    for(int i=1;i<=n;i++) {
        double x,y;
        scanf("%lf%lf",&x,&y);
        p[i] = (POINT) {x,y};
    }
    for(int i=1;i<=m;i++) {
        scanf("%d%d",&posa[i],&posb[i]);
        unions(posa[i],posb[i]);
        dg[i] = (LINE) {p[posa[i]],p[posb[i]]};
    }
//点在线段上
     for(int i=1;i<=n;i++) {
        for(int j=1;j<=m;j++) {
            if(onseg(p[i],dg[j])) {
               unions(i,posa[j]);
               unions(i,posb[j]);
            }
        }
    }

    POINT pp ;//线段交点
    for(int i=1;i<=m;i++) {
        for(int j=1;j<=m;j++) {
            if(inter(dg[i],dg[j])) {
                unions(posa[i],posa[j]);
                unions(posa[i],posb[j]);
                unions(posb[i],posa[j]);
                unions(posb[i],posb[j]);
            }
        }
    }

    int all = 1;
    int fi = finds(1);
    for(int i=1;i<=n;i++) {
        if(finds(i)!=fi) {
            puts("NO");return 0;
        }
    }
    puts("YES");

}
时间: 2024-08-07 08:40:30

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

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 =

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

hdu 1558 线段相交+并查集路径压缩

Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3457    Accepted Submission(s): 1290 Problem Description A segment and all segments which are connected with it compose a segment set.

hdu 1558 (线段相交+并查集) Segment set

题目:http://acm.hdu.edu.cn/showproblem.php?pid=1558 题意是在坐标系中,当输入P(注意是大写,我当开始就wa成了小写)的时候输入一条线段的起点坐标和终点坐标,当输入Q的时候输入n,然后输出与第n条线段相交的线段有多少条 首先判断线段是否相交,在算法导论p577上有介绍 线段A(x1,y1)-B(x2,y2),所在直线L1方程为F1(x,y)=0;线段C(x3,y3)-D(x4,y4),所在直线L2方程为F2(x,y)=0; 如何判断两条线段有交点:(

hdu 1558 线段相交+并查集

题意:要求相交的线段都要塞进同一个集合里 sol:并查集+判断线段相交即可.n很小所以n^2就可以水过 1 #include <iostream> 2 #include <cmath> 3 #include <cstring> 4 #include <cstdio> 5 using namespace std; 6 7 int f[1010]; 8 char ch; 9 int tmp,n; 10 double X1,X2,Y1,Y2; 11 12 #def

花神游历各国 题解(小清新线段树/树状数组+并查集)

众所周知,这是一道小清新线段树 然而可以用树状数组水过去且跑得飞快 看到区间开方第一反应肯定是线段树懒标记区间修改之类的,但是这个东西似乎确凿不可维护 所以考虑暴力循环单点修改->T飞 于是我们关注一下开方本身的特殊性 我们知道,如果每次向下取整,一个数经过多次操作最终会变成1(或0) 事实上,大概经过 log(logx)次就会变成1 这是什么概念呢?经过博主测试,1e9只要经过五次开方取整就会变成1 那么接下来就能够利用1每次不必再操作优化复杂度 可以维护一个类似链表的结构,指向下一个>1的

poj 1127 Jack Straws 线段相交+并查集

题意: 有n个木棍,给出木棍的两个端点的x,y坐标,判断其中某两个线段是否连通(可通过其他线段连通) #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <queue> #include <map> #include <

poj 1127 -- Jack Straws(计算几何判断两线段相交 + 并查集)

Jack Straws In the game of Jack Straws, a number of plastic or wooden "straws" are dumped on the table and players try to remove them one-by-one without disturbing the other straws. Here, we are only concerned with if various pairs of straws are