Cycling Roads URAL 1966 线段相交 + 并查集
来源:互联网 发布:贵州旅游大数据报告 编辑:程序博客网 时间:2024/05/18 02:12
题目:https://vjudge.net/problem/URAL-1966
题意:给出n个点的坐标,并标号为1~n,给出m条线段,线段端点即为标号为1~n的点。判断是否所有点连通,两线段只要有公共点即互相连通。
思路:用叉积判断线段相交,把所有直接连通的点所在集合合并,顺便统计集合数量,最终只剩一个集合就连通。
注意有种情况,把我坑的不轻。数据里有孤立点位于一条线段上的情况,我本以为只要把各种线段相交情况考虑到就行,但还需要单独扫一遍点在线段上的情况。
训练赛的时候用高中解析几何的知识做了两道几何题,另外一道AC了,这道考虑了各种情况也没AC,赛后想想不能一直用高中知识做几何,算坐标考虑斜率不存在的情况就能难受死,于是对着刘汝佳的算法竞赛入门经典训练指南的第四章几何部分学了一下二维几何基础,重新写了一遍然而依旧一直WA,最后发现卡在之前说的坑上。不过好歹几何稍微入了个门。
代码:c++
#include <iostream>#include <cstdio>#include <cmath>#include <map>#include <vector>#include <algorithm>#include <cstring>#include <cstdlib>using namespace std;const double esp = 1e-10;const int maxn = 300;int dcmp(double a){ if (fabs(a) < esp) return 0; else return a < 0 ? -1 : 1;}struct Point{ int id; double x, y; Point(double xx = 0, double yy = 0, int idx = 0) : x(xx), y(yy), id(idx) {} bool operator == (Point p) { return dcmp(x - p.x) == 0 && dcmp(y - p.y) == 0; }};typedef Point Vector;Point points[maxn];Vector operator - (Point A, Point B){ return Vector(A.x - B.x, A.y - B.y);}Vector operator + (Vector A, Vector B){ return Vector(A.x + B.x, A.y + B.y);}double Cross(Vector A, Vector B){ return A.x * B.y - A.y * B.x;}double Dot(Vector A, Vector B){ return A.x * B.x + A.y * B.y;}struct Line{ Point v1, v2; Line(Point p1 = Point(), Point p2 = Point()) : v1(p1), v2(p2) {}};Line lines[maxn];//判断点在线段上bool OnLine(Point p, Line l){ return dcmp(Cross(l.v1 - p, l.v2 - p)) == 0 && dcmp(Dot(l.v1 - p, l.v2 - p)) <= 0;}//判断两线段相交bool LineIntersection(Line l1, Line l2){ if (OnLine(l1.v1, l2) || OnLine(l1.v2, l2) || OnLine(l2.v1, l1) || OnLine(l2.v2, l1)) { return true; } double c1 = Cross(l1.v1 - l2.v1, l1.v1 - l1.v2); double c2 = Cross(l1.v1 - l2.v2, l1.v1 - l1.v2); double c3 = Cross(l2.v1 - l1.v1, l2.v1 - l2.v2); double c4 = Cross(l2.v1 - l1.v2, l2.v1 - l2.v2); return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;}int fa[maxn];int n, m;int setamount;//并查集的各种函数void init(){ setamount = n; for (int i = 1; i <= n; i++) { fa[i] = i; }}int setfind(int u){ return fa[u] == u ? u : fa[u] = setfind(fa[u]);}bool check(int a, int b){ return setfind(a) == setfind(b);}void setunion(int a, int b){ int p1 = setfind(a); int p2 = setfind(b); if (p1 != p2) { fa[p1] = p2; setamount--; }}int main(){ scanf("%d%d", &n, &m); init(); for (int i = 1; i <= n; i++) { double x, y; scanf("%lf%lf", &x, &y); points[i] = Point(x, y, i); } for (int i = 1; i <= m; i++) { int a, b; scanf("%d%d", &a, &b); lines[i] = Line(points[a], points[b]); if (!check(a, b)) { setunion(a, b); } for (int j = 1; j <= n; j++) { if (OnLine(points[j], lines[i])) { setunion(j, a); } } for (int j = 1; j < i; j++) { if (LineIntersection(lines[i], lines[j])) { setunion(lines[i].v1.id, lines[j].v1.id); setunion(lines[i].v2.id, lines[j].v1.id); setunion(lines[i].v1.id, lines[j].v2.id); setunion(lines[i].v2.id, lines[j].v2.id); } } } printf("%s", setamount == 1 ? "YES" : "NO"); return 0;}
阅读全文
0 0
- Cycling Roads URAL 1966 线段相交 + 并查集
- URAL - 1966 - Cycling Roads(并查集 + 判线段相交)
- BNUOJ33566 Cycling Roads(并查集+判断两线段相交)
- hdu1558并查集+线段相交
- hdu1558--并查集+判断线段相交
- hdu 1588 线段相交+并查集
- hdu1558线段相交与并查集
- hdu 1558 并查集+线段相交
- hdu 1558(线段相交+并查集)
- hdu 1558 线段相交判断 + 并查集
- hdu 1558 并查集 加 判断线段相交
- Jack Straws 线段相交加并查集
- HDU 1558 Segment set (并查集+线段相交)
- hdu 1558 Segment set(并查集+线段相交)
- poj1127 Jack Straws 线段相交+并查集
- [poj 1127]Jack Straws[线段相交][并查集]
- hdu 1558 Segment set 线段相交+并查集
- hdu 1558 判断线段相交 + 并查集
- 【求知探新】独立游戏《Abi》场景耗时分析
- Day1-5.Scope of objects
- imindmap10的更新日志
- HDU6075 Questionnaire(思路,2017 HDU多校联赛 第4场)
- POJ 2299 Ultra-QuickSort(树状数组求逆序对)
- Cycling Roads URAL 1966 线段相交 + 并查集
- 证书不安全解决HttpClient 如何忽略证书验证
- WebSocket :Nginx+WebSocket内部路由策略推送服务器的实现(附可生产环境应用代码)
- 通过oracle存储过程实现用户登陆验证
- Day2-6.Fields and methods
- 001
- quad2d函数
- Android actiivty之间传输bitmap数据
- PAT 乙级 1002