AC通道: https://vijos.org/p/1697
[分析]
看到这道题目,我最先想到的是Bzoj1370,明显的并查集呀
我们设直线A‘为与直线A垂直的直线,而互相平行的直线可以互相合并。
若直线A垂直于直线B,则直线A平行于直线B',这样就可以把垂直转换为平行。
具体实现过程请参考代码。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n,m,q;
int fa[2000];
int find(int x){
int tmp=x,pre;
while(tmp!=fa[tmp])tmp=fa[tmp];
while(x!=tmp){
pre=fa[x];
fa[x]=tmp;
x=pre;
}
return tmp;
}
void merge(int x,int y){
int fx=find(x),fy=find(y);
fa[fx]=fy;
}
int main(){
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=2*n;i++)fa[i]=i;
for(int i=1;i<=m;i++){
char c[100],ch;int a,b;
scanf("%s",c);
a=c[1]-'0';
if(c[2]>='0'&&c[2]<='9')a=a*10+c[2]-'0';
if(c[3]>='0'&&c[3]<='9')a=a*10+c[3]-'0';
scanf("%s",c);
ch=c[0];
scanf("%s",c);
b=c[1]-'0';
if(c[2]>='0'&&c[2]<='9')b=b*10+c[2]-'0';
if(c[3]>='0'&&c[3]<='9')b=b*10+c[3]-'0';
if(ch=='p'){
if(find(a)==find(b+n)){
printf("There must be something wrong...\n");
return 0;
}
merge(a,b);
merge(a+n,b+n);
}
else{
if(find(a)==find(b)){
printf("There must be something wrong...\n");
return 0;
}
merge(a+n,b);
merge(a,b+n);
}
}
int nums=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if((find(i)==find(j)||find(i+n)==find(j+n))&&(i!=j))
nums++;
printf("%d\n",nums/2);
for(int i=1;i<=q;i++){
int a,b;
char c[100];
scanf("%s",c);
a=c[1]-'0';
if(c[2]>='0'&&c[2]<='9')a=a*10+c[2]-'0';
if(c[3]>='0'&&c[3]<='9')a=a*10+c[3]-'0';
scanf("%s",c);
b=c[1]-'0';
if(c[2]>='0'&&c[2]<='9')b=b*10+c[2]-'0';
if(c[3]>='0'&&c[3]<='9')b=b*10+c[3]-'0';
if(find(a)==find(b)||find(a+n)==find(b+n)){
printf("Parallel.\n");
}
else if(find(a+n)==find(b)||find(b)==find(a+n))printf("Vertical.\n");
else printf("No idea.\n");
}
return 0;
}