NC200486. 恋爱之子
描述
最近ZSC和他的女朋友NULL吵架了。因为ZSC是一个直男,他不知道该怎么办,于是他寻求恋爱之子磊子哥的帮助。“比起磊子,我更需要女朋友”/doge。
矛盾就如一条条线,纠在一起,越来越乱,ZSC和NULL的矛盾可以看作二维直角坐标系,在平面中有N条线段,线段的两个端点的坐标分别是和。当两个线段有至少一个公共点时,就认为它们是相连的。事情往往都有关联,所以通过相连的线段连在一起的两条线段也是相连的。
恋爱之子磊子哥每次祈祷都可以消除一条线段以及所有与它相连的线段,自从磊子哥成为恋爱之子后特别忙,现在他向你求助“那你能帮帮我吗,我想知道我最少要祈祷几次才能消除所有线段”。学过算法的你,能帮助磊子哥求出最少的次数吗?
输入描述
输入第一行是一个整数,表示线段的个数,接下来N行,每行四个整数表示该线段的两个端点坐标。
输出描述
输出最少需要的祈祷数。
示例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
说明:
C++11(clang++ 3.9) 解法, 执行用时: 299ms, 内存消耗: 872K, 提交时间: 2020-01-04 18:50:31
#include <bits/stdc++.h> using namespace std; int f[100005],mk[100005],ans; struct node { long long x,y; }a[100005]; struct line { node a,b; }l[100005]; int check(line xx,line yy) { node a=xx.a,b=xx.b,c=yy.a,d=yy.b; if(!(min(a.x,b.x)<=max(c.x,d.x) && min(c.y,d.y)<=max(a.y,b.y)&&min(c.x,d.x)<=max(a.x,b.x) && min(a.y,b.y)<=max(c.y,d.y))) return 0; double u,v,w,z; u=(c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y); v=(d.x-a.x)*(b.y-a.y)-(b.x-a.x)*(d.y-a.y); w=(a.x-c.x)*(d.y-c.y)-(d.x-c.x)*(a.y-c.y); z=(b.x-c.x)*(d.y-c.y)-(d.x-c.x)*(b.y-c.y); return(u*v<=0.00000001 && w*z<=0.00000001); } int find(int x) { return f[x]==x?x:f[x]=find(f[x]); } int main() { int n,p=0; scanf("%d",&n); for(int i=1;i<=n;i++) { f[i]=i; scanf("%lld%lld",&a[p].x,&a[p].y); p++; scanf("%lld%lld",&a[p].x,&a[p].y); l[i]=(line){a[p-1],a[p]}; p++; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j) { if(check(l[i],l[j])) f[find(i)]=find(j); } for(int i=1;i<=n;i++) if(!mk[find(i)]) mk[find(i)]=1,ans++; printf("%d",ans); }
C++14(g++5.4) 解法, 执行用时: 137ms, 内存消耗: 732K, 提交时间: 2019-12-28 15:52:21
#include <bits/stdc++.h> #define ll long long using namespace std; const int N=4e3+5; struct Point { ll x,y; }p[N][2]; bool check(Point a,Point b,Point c,Point d) { if(!(min(a.x,b.x)<=max(c.x,d.x)&&min(c.x,d.x)<=max(a.x,b.x)&&min(a.y,b.y)<=max(c.y,d.y)&&min(c.y,d.y)<=max(a.y,b.y))) return false; double u,v,w,z; u=(c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y); v=(d.x-a.x)*(b.y-a.y)-(b.x-a.x)*(d.y-a.y); w=(a.x-c.x)*(d.y-c.y)-(d.x-c.x)*(a.y-c.y); z=(b.x-c.x)*(d.y-c.y)-(d.x-c.x)*(b.y-c.y); return u*v<=1e-9&&w*z<=1e-9; } int f[N]; int Find(int x) { if(x==f[x]) return x; return f[x]=Find(f[x]); } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%lld%lld%lld%lld",&p[i][0].x,&p[i][0].y,&p[i][1].x,&p[i][1].y); f[i]=i; } for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { if(check(p[i][0],p[i][1],p[j][0],p[j][1])) f[Find(i)]=Find(j); } } int ans=0; for(int i=1;i<=n;i++) { if(Find(i)==i) ans++; } printf("%d\n",ans); return 0; }