现在有N条公路,编号从1到N,每条公路是一条线段,用两个端点表示一条公路。如果两条公路之间有交点那么这两条公路可以互通,互通具有传递性,比如A和B互通,B和C互通,那么A就和C互通。
现在给出每条公路的信息以及若干个查询,查询某两条公路之间是否互通。
Input
单组测试数据。 第一行有一个整数N(1 < N < 15),表示公路的数目。 接下来N行,依次给出编号1到N的公路信息,每行给出4个整数xa,ya,xb, yb (-100<=xa,ya,xb, yb<=100),表示公路的两个端点分别是(xa,ya),(xb,yb)。 接下来有若干个查询,每行两个整数u,v(1<=u,v<=N)表示要查询编号为u和v之间是否互通。 查询数目不超过1000。 输入两个0表示查询结束。
Output
对于每一个查询,如果互通输出Yes否则输出No。
Sample Input
样例输入1
7
1 6 3 3
4 6 4 9
4 5 6 7
1 4 3 5
3 5 5 5
5 2 6 3
5 4 7 2
1 4
1 6
3 3
6 7
2 3
1 3
0 0
Sample Output
样例输出1
Yes
No
Yes
Yes
No
Yes
思路:1.并查集模板判断两个路口是否相通;2.利用计算几何的知识判断两条线段是否相加;
参考判断模板:判断两条线段是否相交:https://blog.csdn.net/queque_heiya/article/details/106187844
注意:开辟的数组空间要大!以及并查集一定要初始化,否则答案全是yes||no.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define ll long long
const int maxa=1e2+10;
const double pi=1e-8;
const int inf=0x3f3f3f3f;
int n;
struct node{
int x1,y1;
int x2,y2;
}a[2*maxa];
int par[maxa];
void init(int n){
for(int i=0;i<=n;i++)
par[i]=i;
}
int find(int x){
if(par[x]==x) return x;
else return par[x]=find(par[x]);
}
void unite(int x,int y){
x=find(x);
y=find(y);
if(x==y) return;
else par[x]=y;
}
bool same(int x,int y){
return find(x)==find(y);
}
bool check(node &a,node &b){
if(!(min(a.x1,a.x2)<=max(b.x1,b.x2)
&&min(b.y1,b.y2)<=max(a.y1,a.y2)
&&min(b.x1,b.x2)<=max(a.x1,a.x2)
&&min(a.y1,a.y2)<=max(b.y1,b.y2))) return false;
double u,v,w,z;
u=(b.x1-a.x1)*(a.y2-a.y1)-(a.x2-a.x1)*(b.y1-a.y1);
v=(b.x2-a.x1)*(a.y2-a.y1)-(a.x2-a.x1)*(b.y2-a.y1);
w=(a.x1-b.x1)*(b.y2-b.y1)-(b.x2-b.x1)*(a.y1-b.y1);
z=(a.x2-b.x1)*(b.y2-b.y1)-(b.x2-b.x1)*(a.y2-b.y1);
return (u*v<=pi&&w*z<=pi);
}
int main(){
while(~scanf("%d",&n)){
init(n);
for(int i=1;i<=n;i++)
scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
//并查集判断
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)//判断a[i]与a[j]是否连通
if(check(a[i],a[j])) unite(i,j);
int e1,e2;
while(scanf("%d%d",&e1,&e2)&&(e1+e2)){
if(same(e1,e2)) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define ll long long
const int maxa=1e2+10;
const double pi=0.00000001;
const int inf=0x3f3f3f3f;
int n;
struct nodea{
int x,y;
}a[maxa];
struct nodeb{
int x,y;
}b[maxa];
int par[maxa];
int rank[maxa];
void init(int n){
for(int i=0;i<=n;i++)
par[i]=i,rank[i]=1;
}
int find(int x){
if(par[x]==x) return x;
else return par[x]=find(par[x]);
}
void unite(int x,int y){
x=find(x);
y=find(y);
if(x==y) return;
if(rank[x]<rank[y]) par[x]=y;
else{
par[y]=x;
if(rank[x]==rank[y]) rank[x]++;
}
}
bool same(int x,int y){
return find(x)==find(y);
}
bool check(nodea a,nodeb b,nodea c,nodeb d){
if(!(min(a.x,b.x)<=max(c.x,d.x)
&&min(c.y,d.y)<=max(a.y,b.y)
&&min(c.x,d.x)<=max(a.x,b.x)
&&min(a.y,b.y)<=max(c.y,d.y))) return false;
double u,v,w,z;
u=(c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y);
v=(d.x-a.x)*(b.y-a.y)-(b.x-a.x)*(d.y-a.y);
w=(a.x-c.x)*(d.y-c.y)-(d.x-c.x)*(a.y-c.y);
z=(b.x-c.x)*(d.y-c.y)-(d.x-c.x)*(b.y-c.y);
return (u*v<=pi&&w*z<=pi);
}
int main(){
while(~scanf("%d",&n)){
init(n);
for(int i=1;i<=n;i++)
scanf("%d%d%d%d",&a[i].x,&a[i].y,&b[i].x,&b[i].y);
//并查集判断
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)//判断a[i]与a[j]是否连通
if(check(a[i],b[i],a[j],b[j])) unite(i,j);
int e1,e2;
while(scanf("%d%d",&e1,&e2)&&(e1+e2)){
if(same(e1,e2)) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}