判断线段是否相交
ab cd
用叉积的性质判断 a与cd,b与cd, c与ab,d与ab的关系(模板可以去找一下)
1 floyd 更新联通。
把枚举两两线段,判断是否相交,再用floyd去更新,推广出所有线段之间的联通关系。
代码:
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int mod = 999911659;
const int N = 1010;
struct Node{
int x,y;
};
Node sa[N],en[N];
int dp[N][N],fa[N];
int dir(Node x,Node y,Node z){
int x1 = z.x-x.x,x2 = y.x-x.x;
int y1 = z.y-x.y,y2 = y.y-x.y;
return x1*y2-x2*y1;
}
bool on_segment(Node x,Node y,Node z){
if(z.x >= min(x.x,y.x) && z.x <= max(x.x,y.x) && z.y >= min(x.y,y.y) && z.y <= max(x.y,y.y))
return true;
return false;
}
bool segment_judge(Node x,Node y,Node xx,Node yy){
int d1 = dir(xx,yy,x); // -> 确定 x 在线段xxyy的哪边
int d2 = dir(xx,yy,y); // -> 确定 y 在线段xxyy的哪边
int d3 = dir(x,y,xx); // -> 确定 xx 在线段xy的哪边
int d4 = dir(x,y,yy); // -> 确定 yy 在线段xy的哪边
// 同时满足
if(((d1 < 0 && d2 > 0) || (d1 > 0 && d2 < 0)) && ((d3 < 0 && d4 > 0) || (d3 > 0 && d4 < 0))) return true;
if(d1 == 0 && on_segment(xx,yy,x)) return true;
else if(d2 == 0 && on_segment(xx,yy,y)) return true;
else if(d3 == 0 && on_segment(x,y,xx)) return true;
else if(d4 == 0 && on_segment(x,y,yy)) return true;
else return false;
}
signed main(){
// IOS;
#ifdef ddgo
freopen("C:/Users/asus/Desktop/ddgoin.txt","r",stdin);
#endif
int n;
while(cin>>n){
for(int i=0;i<n;i++){
int x1,y1,x2,y2; cin>>x1>>y1>>x2>>y2;
sa[i] = {x1,y1};
en[i] = {x2,y2};
}
for(int i=0;i<n;i++)
for(int j=i;j<n;j++)
dp[i][j] = dp[j][i] = segment_judge(sa[i],en[i],sa[j],en[j]);
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
dp[i][j] = dp[i][j] | (dp[i][k] & dp[k][j]);
int a,b;
while(cin>>a>>b){
if(a == 0 && b == 0) break;
cout<<(dp[a-1][b-1]?"CONNECTED":"NOT CONNECTED")<<endl;
}
}
return 0;
}
2:
把枚举两两线段,判断是否相交,相交则放入到一个集合。
最后判断两条线段是否在一个集合中即可
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int mod = 999911659;
const int N = 1010;
struct Node{
int x,y;
};
Node sa[N],en[N];
int dp[N][N],fa[N];
int dir(Node x,Node y,Node z){
int x1 = z.x-x.x,x2 = y.x-x.x;
int y1 = z.y-x.y,y2 = y.y-x.y;
return x1*y2-x2*y1;
}
bool on_segment(Node x,Node y,Node z){
if(z.x >= min(x.x,y.x) && z.x <= max(x.x,y.x) && z.y >= min(x.y,y.y) && z.y <= max(x.y,y.y))
return true;
return false;
}
bool segment_judge(Node x,Node y,Node xx,Node yy){
int d1 = dir(xx,yy,x); // -> 确定 x 在线段xxyy的哪边
int d2 = dir(xx,yy,y); // -> 确定 y 在线段xxyy的哪边
int d3 = dir(x,y,xx); // -> 确定 xx 在线段xy的哪边
int d4 = dir(x,y,yy); // -> 确定 yy 在线段xy的哪边
// 同时满足
if(((d1 < 0 && d2 > 0) || (d1 > 0 && d2 < 0)) && ((d3 < 0 && d4 > 0) || (d3 > 0 && d4 < 0))) return true;
if(d1 == 0 && on_segment(xx,yy,x)) return true;
else if(d2 == 0 && on_segment(xx,yy,y)) return true;
else if(d3 == 0 && on_segment(x,y,xx)) return true;
else if(d4 == 0 && on_segment(x,y,yy)) return true;
else return false;
}
int find(int x){
if(x != fa[x]) fa[x] = find(fa[x]);
return fa[x];
}
signed main(){
// IOS;
#ifdef ddgo
freopen("C:/Users/asus/Desktop/ddgoin.txt","r",stdin);
#endif
int n;
while(cin>>n){
for(int i=0;i<n;i++){
int x1,y1,x2,y2; cin>>x1>>y1>>x2>>y2;
sa[i] = {x1,y1};
en[i] = {x2,y2};
}
for(int i=0;i<=n;i++) fa[i] = i;
for(int i=0;i<n;i++)
for(int j=i;j<n;j++)
if(segment_judge(sa[i],en[i],sa[j],en[j]))
fa[find(i)] = find(j);
int a,b;
while(cin>>a>>b){
if(a == 0 && b == 0) break;
cout<<(find(a-1) == find(b-1)?"CONNECTED":"NOT CONNECTED")<<endl;
}
}
return 0;
}