您的位置:首页 > 其它

第五次个人赛D题 Segment set 判断线段相交+并查集

2010-08-04 14:26 441 查看

Segment set

HDU 1558 http://acm.hdu.edu.cn/showproblem.php?pid=1558
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 973 Accepted Submission(s): 396


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就是2部分,线段相交,如果相交就并查:
#include "algorithm"
#include "iostream"
#include "cmath"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
using namespace std;

struct   TPoint {
double   x,y;
};
struct   TLineSeg {
TPoint   a,b;
}a[1001];

double xmulti(TPoint p1,TPoint p2,TPoint p0) {    //(P1-P0)*(P2-P0)的叉积   若结果为正,则<P0,P1>在<P0,P2>的顺时针方向;
return((p1.x-p0.x) * (p2.y-p0.y) -
(p2.x-p0.x) * (p1.y-p0.y));
}

int lsinterls(TLineSeg u,TLineSeg v)  {    //判断2线段是否相交
return( (max(u.a.x,u.b.x)>=min(v.a.x,v.b.x))&&
(max(v.a.x,v.b.x)>=min(u.a.x,u.b.x))&&
(max(u.a.y,u.b.y)>=min(v.a.y,v.b.y))&&
(max(v.a.y,v.b.y)>=min(u.a.y,u.b.y))&&
(xmulti(v.a,u.b,u.a)*xmulti(u.b,v.b,u.a)>=0)&&
(xmulti(u.a,v.b,v.a)*xmulti(v.b,u.b,v.a)>=0));
}

struct boy{       //并查集
int father;
}s[1001];

int getfather(int a){        //并查集

while(1){
if(s[a].father<0)
return a;
a=s[a].father;
}
}

int main(){

int i,j,m,n,T,x,y,k,fin,ans,cnt,num[1001];
char ch[10];
scanf("%d",&T);
while(T--){

scanf("%d",&n);
for(i=0;i<=n;i++) {s[i].father=-1; num[i]=1;}  //初始化
k=0;
for(i=0;i<n;i++)  {
scanf("%s",ch);
if(ch[0]=='P'){         //输入为‘P’的情况
scanf("%lf%lf%lf%lf",&a[k].a.x,&a[k].a.y,&a[k].b.x,&a[k].b.y);
for(j=0;j<k;j++)
if( lsinterls(a[k],a[j]) )  {   //假如相交
x = getfather( k );
y = getfather( j );
if(x!=y){
s[y].father = x;
num[x]+=num[y];
}
}
k++;
}

else{                     //输入为‘Q’的情况
scanf("%d",&fin);
printf("%d/n",num[getfather(fin-1)]);  //或者不用num数组   ans=getfather(fin-1); 再用for循环寻找等于ans的个数  不过时间长一点
}
}
if(T)  printf("/n");
}
//system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: