hdu1558(并查集和简单几何的结合)
Description
A segment and all segments which are connected with it compose a segment set. The size of a segment set is the number of segments in it. The problem is to find the size of some segment set.
Input
In the first line there is an integer t - the number of test case. For each test case in first line there is an integer n (n<=1000) - the number of commands.
There are two different commands described in different format shown below:
P x1 y1 x2 y2 - paint a segment whose coordinates of the two endpoints are (x1,y1),(x2,y2).
Q k - query the size of the segment set which contains the k-th segment.
k is between 1 and the number of segments in the moment. There is no segment in the plane at first, so the first command is always a P-command.
There are two different commands described in different format shown below:
P x1 y1 x2 y2 - paint a segment whose coordinates of the two endpoints are (x1,y1),(x2,y2).
Q k - query the size of the segment set which contains the k-th segment.
k is between 1 and the number of segments in the moment. There is no segment in the plane at first, so the first command is always a P-command.
Output
For each Q-command, output the answer. There is a blank line between test cases.
Sample Input
1 10 P 1.00 1.00 4.00 2.00 P 1.00 -2.00 8.00 4.00 Q 1 P 2.00 3.00 3.00 1.00 Q 1 Q 3 P 1.00 4.00 8.00 2.00 Q 2 P 3.00 3.00 6.00 -2.00 Q 5
Sample Output
1 2 2 2 5
首先这题就得解决线段相交的判断问题,欢迎观看本博客的简单几何内容;
然后重点来了,并查集,还是和基础并查集一样儿一样儿的,不过,这里有个记录问题,记录每个父亲的儿子数量,我用num数组来记录,在合并的时候将后来的父亲加上先前两个父亲的num值就ok了,不过写博客的时候突然想到了一种脑洞办法——遍历(hhhhhhhhh)试了一下也还是过了,艾玛自己想数组的办法想了好久好久结果一来写博客想到了脑洞办法竟然也可以过,亏我想数组办法调试了好久好久啊啊啊啊!!!
#include <iostream> #include<algorithm> #include<stdio.h> #include<memory.h> using namespace std; typedef struct node { double x,y; }Point; typedef struct line { Point start,end; }vector; double mul(Point p1,Point p2,Point p0) { return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x); } bool cross(vector v1,vector v2) { if(max(v1.start.x,v1.end.x)>=min(v2.start.x,v2.end.x)&& max(v2.start.x,v2.end.x)>=min(v1.start.x,v1.end.x)&& max(v1.start.y,v2.end.y)>=min(v2.start.y,v2.end.y)&& max(v2.start.y,v2.end.y)>=min(v1.start.y,v1.end.y)&& mul(v2.start,v1.end,v1.start)*mul(v1.end,v2.end,v1.start)>=0&& mul(v1.start,v2.end,v2.start)*mul(v2.end,v1.end,v2.start)>=0 ) return true; return false; } vector f[100010];int fa[100010];int num[100010]; int ff(int x) { int tem=fa[x]; if(tem!=x) fa[x]=ff(tem); return fa[x]; } void join(int a,int b) { int tem=num[fa[ff(a)]]+num[fa[ff(b)]]; fa[ff(a)]=fa[ff(b)]; // cout<<a<<' '<<b<<endl; // cout<<fa[ff(a)]<<endl; // cout<<" num[fa[ff(a)]] = "<<num[fa[ff(a)]]<<" num[fa[ff(b)]] = "<<num[fa[ff(a)]]<<endl; num[fa[ff(a)]]=tem; //cout<<a<<" and "<<b<<"de father shi "<<ff(a)<<endl; // cout<<"zhe ge ji he bao han "<<num[fa[ff(a)]]<<" ge xian duan"<<endl; } int main() { int t; scanf("%d",&t); for(int u=0;u<t;u++) { for(int i=0;i<100010;i++) fa[i]=i; memset(num,0,sizeof(num)); int n; scanf("%d",&n); int g=0; for(int i=1;i<=n;i++) { char cc;scanf(" %c",&cc); if(cc=='P') { g++; scanf("%lf%lf%lf%lf",&f[g].start.x,&f[g].start.y,&f[g].end.x,&f[g].end.y); num[g]++; for(int j=1;j<g;j++) if(cross(f[g],f[j])>0&&ff(fa[g])!=ff(fa[j])) join(fa[g],fa[j]); } else { int p; scanf("%d",&p); printf("%d\n",num[ff(fa[p])]); } } if(u!=t-1) printf("\n"); } return 0; }
下面是脑洞代码:
#include <iostream> #include<algorithm> #include<stdio.h> #include<memory.h> using namespace std; typedef struct node { double x,y; }Point; typedef struct line { Point start,end; }vector; double mul(Point p1,Point p2,Point p0) { return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x); } bool cross(vector v1,vector v2) { if(max(v1.start.x,v1.end.x)>=min(v2.start.x,v2.end.x)&& max(v2.start.x,v2.end.x)>=min(v1.start.x,v1.end.x)&& max(v1.start.y,v2.end.y)>=min(v2.start.y,v2.end.y)&& max(v2.start.y,v2.end.y)>=min(v1.start.y,v1.end.y)&& mul(v2.start,v1.end,v1.start)*mul(v1.end,v2.end,v1.start)>=0&& mul(v1.start,v2.end,v2.start)*mul(v2.end,v1.end,v2.start)>=0 ) return true; return false; } vector f[100010];int fa[100010]; int ff(int x) { int tem=fa[x]; if(tem!=x) fa[x]=ff(tem); return fa[x]; } void join(int a,int b) { fa[ff(a)]=fa[ff(b)]; } int main() { int t; scanf("%d",&t); for(int u=0;u<t;u++) { for(int i=0;i<100010;i++) fa[i]=i; int n; scanf("%d",&n); int g=0; for(int i=1;i<=n;i++) { char cc;scanf(" %c",&cc); if(cc=='P') { g++; scanf("%lf%lf%lf%lf",&f[g].start.x,&f[g].start.y,&f[g].end.x,&f[g].end.y); for(int j=1;j<g;j++) if(cross(f[g],f[j])>0&&ff(fa[g])!=ff(fa[j])) join(fa[g],fa[j]); } else { int p; scanf("%d",&p); int t=ff(p),s=0; for(int i=0;i<=g;i++) if(ff(i)==t) s++; printf("%d\n",s); } } if(u!=t-1) printf("\n"); } return 0; }
持续更新博客地址:
blog.csdn.net/martinue