hdu 1558 http://acm.hdu.edu.cn/showproblem.php?pid=1558
很久没有a题 一些小细节都忘了输出错了了几次,并查集的最基本方式都差点忘了,今天小复习一下。比较简单的并查集,先判断两个线段相交,再用并查集看是否合
并,只要注意集合大小的合并即可解决,下面是code:
#include <cstdio>
const int maxn=10000;
int father[maxn];
int num[maxn];
struct Segment{
double x1,y1; //表示线段
double x2,y2;
}s[maxn];
double x,y;
void Init(){
for(int i=0;i<maxn;i++){
father[i]=i;
num[i]=1;
}
}
int Find(int x){
if(father[x]==x) return x;
return father[x]=Find(father[x]);
}
void UnionSet(int i,int j){
father[j]=i;
num[i]+=num[j];
}
void Solve(Segment s1,Segment s2)
{
if(s1.x2==s1.x1&&s2.x2!=s2.x1)
{
x=s1.x2;
y=((s2.y2-s2.y1)/(s2.x2-s2.x1))*(x-s2.x2)+s2.y2;
}
else{
if(s2.x2==s2.x1&&s1.x2!=s1.x1)
{
x=s2.x2;
y=((s1.y2-s1.y1)/(s1.x2-s1.x2))*(x-s1.x2)+s1.y2;
}
else
{
double k1=(s1.y2-s1.y1)/(s1.x2-s1.x1);
double k2=(s2.y2-s2.y1)/(s2.x2-s2.x1);
double b1=s1.y2-k1*s1.x2;
double b2=s2.y2-k2*s2.x2;
x=(b2-b1)/(k1-k2);
y=k1*x+b1;
}
}
}
bool Dic(Segment s1){
double tx1=s1.x1<s1.x2?s1.x1:s1.x2;
double ty1=s1.y1<s1.y2?s1.y1:s1.y2;
double tx2=s1.x1>s1.x2?s1.x1:s1.x2;
double ty2=s1.y1>s1.y2?s1.y1:s1.y2;
if(tx1<=x&&x<=tx2&&ty1<=y&&y<=ty2)
return true;
return false;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
Init();
int k=0;
while(n--){
char op[5];
scanf("%s",op);
if(op[0]=='P'){
x=maxn;
y=maxn;
scanf("%lf%lf%lf%lf",&s[k].x1,&s[k].y1,&s[k].x2,&s[k].y2);
for(int i=0;i<=k-1;i++){
Solve( s[i], s[k]);
if(Dic(s[i])&&Dic(s[k])){
int ti=Find(i);
int tj=Find(k);
if(ti!=tj){
UnionSet(ti,tj);
// break;
}
}
}
k++;
}
else{
int k1;
scanf("%d",&k1);
k1=Find((k1-1));
printf("%d\n",num[k1]);
}
}
if(t>0) puts("");
}
return 0;
}