Segment set
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3599 Accepted Submission(s): 1346
Problem 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.
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
分析:这道题是道基础带权并查集的题,主要就是如何判断两条线段相交(注意:是线段)
有一个链接:http://blog.csdn.net/rickliuxiao/article/details/6259322
为了确定两条线段是否相交,要检查每个线段是否跨越了包含另一线段的直线。 给定一个线段p1p2,如果点p1位于某一直线的一边, 而点p2位于直线的另一边,则称线段p1p2跨越了该直线。如果p1和p2 就落在该直线的话,即出现边界情况。两条线段相交, 当且仅当下面两个条件中有一个成立,或同时成立:
1)每个线段都跨越包含了另一线段的直线。
2)一个线段的某一端点位于另一线段上。
- #include<stdio.h>
- #include<string.h>
- #include<algorithm>
- #include<iostream>
- #define Min(a,b) a<b?a:b
- #define Max(a,b) a>b?a:b
- #define maxh 1000+10
- using namespace std;
- typedef struct{
- double x,y;
- }point;
- typedef struct{
- point p0,p1;
- }node;
- node E[maxh];
- int set[maxh],rank[maxh];
- void init(){
- for(int i=0;i<maxh;i++){
- set[i]=i,rank[i]=1;
- }
- }
- int findx(int x){
- if(x==set[x])
- return x;
- set[x]=findx(set[x]);
- return set[x];
- }
- void Union(int x,int y){
- x=findx(x);
- y=findx(y);
- if(x!=y){
- set[x]=y;
- rank[y]+=rank[x];
- }
- }
- double direction(point p0,point p1,point p2){
- return ((p2.x-p0.x)*(p1.y-p0.y)-(p1.x-p0.x)*(p2.y-p0.y));
- }
- bool on(point p0,point p1,point p2){
- double xmin,ymin,xmax,ymax;
- xmin=Min(p0.x,p1.x);
- xmax=Max(p0.x,p1.x);
- ymin=Min(p0.y,p1.y);
- ymax=Max(p0.y,p1.y);
- if(p2.x>=xmin&&p2.x<=xmax&&p2.y>=ymin&&p2.y<=ymax)
- return true;
- return false;
- }
- bool intersect(point p0,point p1,point p2,point p3){
- double d0,d1,d2,d3;
- d0=direction(p2,p3,p0);
- d1=direction(p2,p3,p1);
- d2=direction(p0,p1,p2);
- d3=direction(p0,p1,p3);
- // printf("%lf %lf %lf %lf\n",d0,d1,d2,d3);
- if(((d0<0&&d1>0)||(d0>0&&d1<0))&&((d2>0&&d3<0)||(d2<0&&d3>0))){
- // printf("cwefg");
- return true;
- }
- else if(d0==0&&on(p2,p3,p0))
- return true;
- else if(d1==0&&on(p2,p3,p1))
- return true;
- else if(d2==0&&on(p0,p1,p2))
- return true;
- else if(d3==0&&on(p0,p1,p3))
- return true;
- else
- return false;
- }
- int main(){
- int T,n,h,x;
- char c[2];
- scanf("%d",&T);
- while(T--){
- scanf("%d",&n);
- init();
- h=1;
- while(n--){
- scanf("%s",c);
- if(c[0]==‘P‘){
- scanf("%lf%lf%lf%lf",&E[h].p0.x,&E[h].p0.y,&E[h].p1.x,&E[h].p1.y);
- for(int i=1;i<h;i++){
- if(intersect(E[i].p0,E[i].p1,E[h].p0,E[h].p1)){
- // printf("<%d,%d>\n",i,h);
- Union(i,h);
- }
- }
- h++;
- }
- else{
- scanf("%d",&x);
- printf("%d\n",rank[findx(x)]);
- }
- }
- if(T){
- printf("\n");
- }
- }
- return 0;
- }