I、恋爱之子
链接:https://ac.nowcoder.com/acm/contest/3570/I
来源:牛客网
题目描述
最近ZSC和他的女朋友NULL吵架了。因为ZSC是一个直男,他不知道该怎么办,于是他寻求恋爱之子磊子哥的帮助。“比起磊子,我更需要女朋友”/doge。
矛盾就如一条条线,纠在一起,越来越乱,ZSC和NULL的矛盾可以看作二维直角坐标系,在平面中有N条线段,线段的两个端点的坐标分别是 pi_x,pi_y和qi_x,qi_y。当两个线段有至少一个公共点时,就认为它们是相连的。事情往往都有关联,所以通过相连的线段连在一起的两条线段也是相连的。
恋爱之子磊子哥每次祈祷都可以消除一条线段以及所有与它相连的线段,自从磊子哥成为恋爱之子后特别忙,现在他向你求助“那你能帮帮我吗,我想知道我最少要祈祷几次才能消除所有线段”。学过算法的你,能帮助磊子哥求出最少的次数吗?
输入描述:
输入第一行是一个整数N(1≤N≤4∗103),表示线段的个数,接下来N行,每行四个整数pi_x,pi_y和qi_x,qi_y表示该线段的两个端点坐标。
输出描述: 输出最少需要的祈祷数。
示例1
输入
复制
4
0 0 6 0
6 -4 6 4
0 4 4 4
2 2 2 6
输出
2
说明
示例2
输入
复制
3
0 1 1 0
0 2 2 0
0 3 3 0
输出
复制
3
说明
示例3
输入
复制
29
1 8 2 9
2 9 11 9
11 9 9 8
9 8 1 8
1 6 2 7
2 7 2 8
3 6 5 8
5 6 6 7
6 7 6 8
7 6 9 8
7 7 8 8
1 3 1 5
1 5 3 5
3 5 3 3
3 3 1 3
2 1 2 3
0 2 2 2
2 2 4 2
1 -1 2 1
3 -1 2 1
5 3 5 5
5 5 7 5
7 5 7 3
7 3 5 3
6 1 6 3
4 2 6 2
6 2 8 2
5 -1 6 1
7 -1 6 1
输出
复制
2
说明
思路如下
题意:题目给出 n 条直线的端点,通过每次次的祈祷,可以把其中相交的线段都去掉,问我们需要祈祷多少次才可以,把所有线段都消除,那么我们就要考虑两个问题:怎么判断直线相交、怎么一次把所有相交的直线都消去。对于前一个问题我也没看懂到大佬的题解,但对于第二个问题,我们可以明确的看出可以并查集来解决,通过判断线段相交,把所有的相交的线段视为一个集合,这样有几个集合我们就需要祈祷 几次
并查集总结传送门
题解如下(贴出大佬的代码一起共赏)
#include<set>
#include<map>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<string>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#define fi first
#define se second
#define db double
#define gcd __gcd
#define pb push_back
#define lowbit(x) (x & (-x))
#define PII pair<int, int>
#define all(x) x.begin(), x.end()
#define debug(x) cout << #x << " = " << x << endl
#define rep(i, a, b) for(__typeof(b) i = a; i <= (b); i++)
#define Rep(i, a, b) for(__typeof(a) i = a; i >= (b); i--)
#define Mod(a,b) a<b?a:a%b+b
template<class T> inline T qmin(T a, T b) { return a < b ? a : b; }
template<class T> inline T qmax(T a, T b) { return a > b ? a : b; }
typedef long long ll;
typedef unsigned long long ull;
const db PI = acos(-1);
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 1;
const int maxn = (int)1e5 + 5;//remember to modify it, No RE&nbs***bsp;MLE
const ll INF = 0x3f3f3f3f3f3f3f3f;
using namespace std;
#define cross(p1, p2, p3) ((p2.x - p1.x) * (p3.y - p1.y) - (p3.x - p1.x) * (p2.y - p1.y))
#define cross0p(p1, p2, p3) sign(cross(p1,p2,p3))
const db eps = 1e-9;
inline int sign(db a) { return a < -eps ? -1: a > eps; }
inline int cmp(db a, db b) { return sign(a-b); }
struct P{
db x, y;
P() {}
P(db _x, db _y): x(_x), y(_y) {}
P operator+(P p) { return {x + p.x, y + p.y}; }
P operator-(P p) { return {x - p.x, y - p.y}; }
P operator*(db d) { return {x * d, y * d}; }
P operator/(db d) { return {x / d, y / d}; }
bool operator<(P p)const {
int c = cmp(x, p.x);
if(c) return c == -1;
return cmp(y, p.y) == -1;
}
bool operator==(P o) const {
return cmp(x, o.x) == 0 && cmp(y, o.y) == 0;
}
db distTo(P p) { return (*this - p).abs(); }
db abs() { return sqrt(abs2()); }
db abs2() { return x * x + y * y; }
db dot(P p) { return x * p.x + y * p.y; }
db det(P p) { return x * p.y - y * p.x; }
};
bool intersect(db l1, db r1, db l2, db r2)
{
if(l1 > r1)swap(l1, r1); if(l2 > r2) swap(l2, r2);
return !( cmp(r1, l2) == -1 || cmp(r2, l1) == -1);
}
bool isSS(P p1, P p2, P q1, P q2){
return intersect(p1.x, p2.x, q1.x, q2.x) && intersect(p1.y, p2.y, q1.y, q2.y) && cross0p(p1, p2, q1) * cross0p(p1, p2, q2) <= 0 && cross0p(q1, q2, p1) * cross0p(q1, q2, p2) <= 0;
}
//并查集开始
int f[maxn];
int find(int x) //递归查找x元素的父节点
{
if(f[x] == x)
return x;
return f[x] = find(f[x]); //注意这里在查找父节点的时候 已经把节点的路径进行了压缩(进行了优化)
}
void Union(int x,int y)
{
int fx = find(x),fy = find(y);
if(fx != fy) f[fx] = fy; //x,y是是有关系的,但是他们的父节点不同所以要 把其中的一个赋接待你作为子节点 拼接到临一个父节点上
} //这样x、 y 就有了相同的父节点,就属于同一个集合了
int main()
{
int n;
P p[10005], q[10005];
scanf("%d", &n);
for(int i = 1 ; i <= n ; i++){
f[i] = i; //并查集元素的初始化
scanf("%lf %lf %lf %lf", &p[i].x, &p[i].y, &q[i].x, &q[i].y);
}
for(int i = 1 ; i <= n ; i++){
for(int j = i + 1 ; j <= n ; j++){
if(isSS(p[i], q[i], p[j], q[j]))Union(i, j);//如果为真i,j 是有关系的,所以他们应该在同一个集合中
}
}
int ans = 0;
for(int i = 1 ; i <= n ; i++)if(f[i] == i)ans++;
printf("%d\n", ans);
return 0;
}
I、恋爱之子的更多相关文章
- XXOOJL
她的鞋子放在外面没拿进来很显眼,我们俩正抱在床上,刚做完什么也没穿,她也没擦.听到门外的脚步声.赶紧穿.她在我房间里没出声,但我父亲肯定看出来了.于是问我:母亲去哪了,然后他去找她. 太尴尬了,那晚我 ...
- 【0门槛】PR稿的自我修养
本文来自网易云社区 作者:巩爽 十一过完,离2018年结束就只剩下85天啦!是不是2016年许下的2017年的梦想,在2018年还没有实现? 做过的项目仿佛都小有成就,可惜只是内部自嗨,想做域外宣传却 ...
- 二狗子 、初恋及HTTPS
最近二狗子宅在老家,最悠闲的就是泡壶茶看着院子的风景发呆一下午.今天,二狗子看到了对面自己暗恋的小翠花,看着美好的小翠花二狗子不禁想起了自己美好的初恋. 二狗子的初恋在初中,那个时候学校禁止带手机.上 ...
- 深入理解MySql子查询IN的执行和优化
IN为什么慢? 在应用程序中使用子查询后,SQL语句的查询性能变得非常糟糕.例如: SELECT driver_id FROM driver where driver_id in (SELECT dr ...
- Hawk 6. 高级话题:子流程系统
子流程的定义 当流程设计的越来越复杂,越来越长时,就难以进行管理了.因此,采用模块化的设计才会更加合理.本节我们介绍子流程的原理和使用. 所谓子流程,就是能先构造出一个流程,然后被其他流程调用.被调用 ...
- margin折叠-从子元素margin-top影响父元素引出的问题
正在做一个手机端电商项目,顶部导航栈的布局是一个div包含一个子div,如果给在正常文档流中的子div一个垂直margin-top,神奇的现象出现了,两父子元素的边距没变,但父div跟着一起往下走了! ...
- DevExpress第三方控件使用实例之ASPxPopupControl弹出子窗体
弹出页面控件:ASPxPopupControl, <dxpc:ASPxPopupControl ID="popubCtr" runat="server" ...
- Mysql - 性能优化之子查询
记得在做项目的时候, 听到过一句话, 尽量不要使用子查询, 那么这一篇就来看一下, 这句话是否是正确的. 那在这之前, 需要介绍一些概念性东西和mysql对语句的大致处理. 当Mysql Server ...
- 面向组合子设计Coder
面向组合子 面向组合子(Combanitor-Oriented),是最近帮我打开新世界大门的一种pattern.缘起haskell,又见monad与ParseC,终于ajoo前辈的几篇文章. 自去年9 ...
随机推荐
- Eclipse+Mysql实现多条件查询
最近做一个项目的时候,就需要用到多条件查询,但是一直不完美,所有有bug,不过今天经高人提醒,做出了个小例子,在这里简单跟大家分享一下: 不说多了,直接放关键sql代码: 已知条件:菜名,菜品,价格区 ...
- 使用ZXingObjC扫描二维码横竖屏对应
/** 根据屏幕的方向设置扫描的方向 * @author maguang * @param parameter * @return result */ - (void)showaCapture { C ...
- 在Linux上查询物理机信息-不用去拆机器了
目录 一.查看系统信息(包含机器型号) 1.1 查看机型和品牌 二.查看CPU 信息 2.1 查看CPU 型号 2.2 查看CPU的物理数量 2.3 查看 CPU核心数量(非逻辑CPU) 2.4 查看 ...
- 结题报告--P2441角色属性树
题目:点此 题目描述 绪萌同人社是一个有趣的组织,该组织结构是一个树形结构.有一个社长,直接下属一些副社长.每个副社长又直接下属一些部长……. 每个成员都有一个萌点的属性,萌点属性是由一些质数的萌元素 ...
- .NET实现一个简单的IOC容器
目录 1.主要细节 2.具体示例 参考及示例代码下载 shanzm-2020年3月17日 20:06:01 1.主要细节 使用反射程序集的方式获取对象的类型 通过反射的方式获取指定类型的的所有公共属性 ...
- 你知道吗,Flutter内置了10多种show
注意:无特殊说明,Flutter版本及Dart版本如下: Flutter版本: 1.12.13+hotfix.5 Dart版本: 2.7.0 showDialog showDialog 用于弹出Mat ...
- VS配置C++依赖包
处理好三个东西 1.头文件,Configuration Properties → VC++ Directories → Include Directories 2.静态库,Configuration ...
- Scala尾递归
递归函数应用 首先,我们来对比两个递归方法的求值步骤. 假设有方法gcd,用来计算两个数的最大公约数.下面是欧几里得算法的实现: def gcp(a: Int, b: Int): Int = if ( ...
- 蓝桥杯vip题阶乘计算
蓝桥杯vip题阶乘计算 详细题目 输入一个正整数n,输出n!的值. 其中n!=123*-*n. 算法描述 n!可能很大,而计算机能表示的整数范围有限,需要使用高精度计算的方法.使用一个数组A来表示一个 ...
- 如何用 Blazor 实现 Ant Design 组件库
本文主要分享我创建 Ant Design of Blazor 项目的心路历程,已经文末有一个 Blazor 线上分享预告. Blazor WebAssembly 来了! Blazor 这个新推出的前端 ...