HLG 1507 水神的栅栏【判断线段相交+并查集】
Description |
水神在赚了一笔钱之后,购买了一座庄园,做起了农场主,水神的农场都是靠栅栏围墙来分成很多部分并且围成外面的围墙的,但是最近一段时间,水神的庄园遭到了神兽的袭击,神兽撞破了很多处栅栏,这让水神非常苦恼,为了弄清楚自己的栅栏还有哪些地方时连着的,水神画了一张平面图,每一段栅栏在图上表示成一个线段,这些线段有的会相交,有的不会。 水神需要知道两段栅栏是否可以连起来。 |
Input |
有多组输入数据,每组数据: 第一行一个整数n表示水神农场的栅栏的个数(n<13) 接下来n行,每行四个整数x1,y1,x2,y2分别表示栅栏的两个端点坐标 然后下面若干行是对栅栏连接情况的询问,每行两个整数a,b表示水神想知道,栅栏a和栅栏b是否可以连起来。询问以0 0结束。 当n=0时输入结束 |
Output |
对于每次询问,如果栅栏a和b可以连起来,输出” CONNECTED”,否则输出:”NOT CONNECTED”. |
Sample Input |
2 0 2 0 0 0 0 0 1 1 1 2 2 1 2 0 0 2 0 2 0 0 1 0 2 0 1 2 0 0 0 |
Sample Output |
CONNECTED CONNECTED CONNECTED NOT CONNECTED |
思路:如果两条线段相交,则他们之间相连,两个几何并在一起。
代码如下:
#include<stdio.h> #include<string.h> #include<iostream> using namespace std; struct point { int x1, y1, x2, y2; }; int f[20]; int find(int x) { return x==f[x]?f[x]:f[x]=find(f[x]); } int mul(int ax, int ay, int bx, int by, int cx, int cy) { return (ax-cx)*(by-cy)-(bx-cx)*(ay-cy); } int main() { int i, j, n, qx, qy; while(scanf("%d", &n)!=EOF) { if(n==0) break; for(i=0; i<=15; i++) f[i]=i; point p[20]; for(i=1; i<=n; i++) scanf("%d%d%d%d", &p[i].x1, &p[i].y1, &p[i].x2, &p[i].y2); for(i=1; i<=n; i++) for(j=i+1; j<=n; j++) { if((max(p[i].x1, p[i].x2)>=min(p[j].x1, p[j].x2)) &&(max(p[j].x1, p[j].x2)>=min(p[i].x1, p[i].x2)) &&(max(p[i].y1, p[i].y2)>=min(p[j].y1, p[j].y2)) &&(max(p[j].y1, p[j].y2)>=min(p[i].y1, p[i].y2)) &&(mul(p[j].x1, p[j].y1, p[i].x2, p[i].y2, p[i].x1, p[i].y1) *mul(p[i].x2, p[i].y2, p[j].x2, p[j].y2, p[i].x1, p[i].y1)>=0) &&(mul(p[i].x1, p[i].y1, p[j].x2, p[j].y2, p[j].x1, p[j].y1) *mul(p[j].x2, p[j].y2, p[i].x2, p[i].y2, p[j].x1, p[j].y1)>=0)) { int xx=find(i); int yy=find(j); if(xx<yy) f[xx]=yy; else f[yy]=xx; } } while(1) { scanf("%d%d", &qx, &qy); if(qx==0&&qy==0) break; int xx=find(qx); int yy=find(qy); if(xx==yy) printf("CONNECTED\n"); else printf("NOT CONNECTED\n"); } } }