Jack Straws
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 2624 | Accepted: 1183 |
Description
In the game of Jack Straws, a number of plastic or wooden "straws" are dumped on the table and players try to remove them one-by-one without disturbing the other straws. Here, we are only concerned with if various pairs of straws are connected by a path of touching straws. You will be given a list of the endpoints for some straws (as if they were dumped on a large piece of graph paper) and then will be asked if various pairs of straws are connected. Note that touching is connecting, but also two straws can be connected indirectly via other connected straws.
Input
Input consist multiple case,each case consists of multiple lines. The first line will be an integer n (1 < n < 13) giving the number of straws on the table. Each of the next n lines contain 4 positive integers,x1,y1,x2 and y2, giving the coordinates, (x1,y1),(x2,y2) of the endpoints of a single straw. All coordinates will be less than 100. (Note that the straws will be of varying lengths.) The first straw entered will be known as straw #1, the second as straw #2, and so on. The remaining lines of the current case(except for the final line) will each contain two positive integers, a and b, both between 1 and n, inclusive. You are to determine if straw a can be connected to straw b. When a = 0 = b, the current case is terminated.
When n=0,the input is terminated.
There will be no illegal input and there are no zero-length straws.
When n=0,the input is terminated.
There will be no illegal input and there are no zero-length straws.
Output
You should generate a line of output for each line containing a pair a and b, except the final line where a = 0 = b. The line should say simply "CONNECTED", if straw a is connected to straw b, or "NOT CONNECTED", if straw a is not connected to straw b. For our purposes, a straw is considered connected to itself.
Sample Input
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 2 0 2 0 0 0 0 0 1 1 1 2 2 1 2 0 0 0
Sample Output
CONNECTED NOT CONNECTED CONNECTED CONNECTED NOT CONNECTED CONNECTED CONNECTED CONNECTED CONNECTED
1 /* 功能Function Description: POJ-1127 2 开发环境Environment: DEV C++ 4.9.9.1 3 技术特点Technique: 4 版本Version: 5 作者Author: 可笑痴狂 6 日期Date: 20120817 7 备注Notes: 8 题意: 9 首先给出一个n,表示共有n条边,下面n行(编号1-n)每行给出4个数分别表示起始点的横纵坐标 10 以及终止点的横纵坐标。接下来的若干行为查询条件,要你输出查询的两条边是否有关系 11 (即直接相交或间接相交)。 12 思路: 13 线段相交判断+并查集 14 判断第i条和第j条线段是否相交的充要条件是: 15 第i条线段的两端点在第j条线段所在直线的两侧 且 第j条线段的两端点在第i条线段所在直线的两侧 16 (端点也可以位于相应的直线上) 17 + 特殊情况的判断-----共线的情况 18 19 */ 20 21 //代码一:----wrong answer -----纠结一天了也找不到原因 22 #include<stdio.h> 23 24 int set[30]; 25 double coord[30][4]; //coord[i][0]、coord[i][1]、coord[i][2]、coord[i][3]分别存储第i条线段两端点的坐标: x1,y1,x2,y2 26 27 int judge(int i,int j) //判断第i条和第j条线段是否相交的充要条件是: 第i条线段的两端点在第j条线段所在直线的两侧 且 第j条线段的两端点在第i条线段所在直线的两侧 28 { 29 int flag1,flag2; 30 double max1,min1,max2,min2; 31 flag1=flag2=0; 32 33 //共线的情况 34 if((coord[i][3]-coord[i][1])*(coord[j][2]-coord[j][0])-(coord[j][3]-coord[j][1])*(coord[i][2]-coord[i][0])<0.0000001) //j与i 平行 35 { 36 max1=coord[i][0]>coord[i][2]?coord[i][0]:coord[i][2]; 37 min1=coord[i][0]<coord[i][2]?coord[i][0]:coord[i][2]; 38 max2=coord[j][0]>coord[j][2]?coord[j][0]:coord[j][2]; 39 min2=coord[j][0]<coord[j][2]?coord[j][0]:coord[j][2]; 40 if(coord[i][0]==coord[i][2]) //直线i与x轴垂直 41 { 42 if(coord[j][0]==coord[i][0]) //直线i与直线j所在直线重合 43 if(max1>=min2&&max1<=max2||min1>=min2&&min1<=max2||max2>=min1&&max2<=max1||min2>=min1&&min2<=max1) 44 return 1; 45 } 46 else //不与x轴垂直的话直接判断j的两个端点是否在直线i上就可以了 47 { 48 if(((coord[i][3]-coord[i][1])/(coord[i][2]-coord[i][0])*coord[j][0]+coord[i][1]-(coord[i][3]-coord[i][1])/(coord[i][2]-coord[i][0])*coord[i][0]-coord[j][1])<0.0000001) 49 if(max1>=min2&&max1<=max2||min1>=min2&&min1<=max2||max2>=min1&&max2<=max1||min2>=min1&&min2<=max1) 50 return 1; 51 } 52 } 53 //不共线的情况下判断线段j是否在线段i所在直线的两侧 54 if(coord[i][0]==coord[i][2]) //直线i与x轴垂直 55 { 56 if((coord[j][0]-coord[i][0])*(coord[j][2]-coord[i][0])<=0) 57 flag1=1; 58 } 59 else 60 { 61 if(((coord[i][3]-coord[i][1])/(coord[i][2]-coord[i][0])*coord[j][0]+coord[i][1]-(coord[i][3]-coord[i][1])/(coord[i][2]-coord[i][0])*coord[i][0]-coord[j][1])* 62 ((coord[i][3]-coord[i][1])/(coord[i][2]-coord[i][0])*coord[j][2]+coord[i][1]-(coord[i][3]-coord[i][1])/(coord[i][2]-coord[i][0])*coord[i][0]-coord[j][3])<=0) 63 flag1=1; 64 } 65 66 //判断线段i是否在线段j所在直线的两侧 67 if(coord[j][0]==coord[j][2]) //直线j与x轴垂直 68 { 69 if((coord[i][0]-coord[j][0])*(coord[i][2]-coord[j][0])<=0) 70 flag2=1; 71 } 72 else 73 { 74 if(((coord[j][3]-coord[j][1])/(coord[j][2]-coord[j][0])*coord[i][0]+coord[j][1]-(coord[j][3]-coord[j][1])/(coord[j][2]-coord[j][0])*coord[j][0]-coord[i][1])* 75 ((coord[j][3]-coord[j][1])/(coord[j][2]-coord[j][0])*coord[i][2]+coord[j][1]-(coord[j][3]-coord[j][1])/(coord[j][2]-coord[j][0])*coord[j][0]-coord[i][3])<=0) 76 flag2=1; 77 } 78 if(flag1&&flag2) 79 return 1; 80 else 81 return 0; 82 } 83 84 int find(int i) 85 { 86 if(i!=set[i]) //--------压缩路径 87 set[i]=find(set[i]); 88 return set[i]; //注意这里不能写成i,就这一点写错了调试了半天 89 } 90 91 void merge(int i,int j) 92 { 93 i=find(i); 94 j=find(j); 95 if(i!=j) 96 set[i]=j; 97 } 98 99 int main() 100 { 101 int n,i,j; 102 while(scanf("%d",&n),n) 103 { 104 for(i=1;i<=n;++i) 105 set[i]=i; 106 for(i=1;i<=n;++i) 107 scanf("%lf%lf%lf%lf",&coord[i][0],&coord[i][1],&coord[i][2],&coord[i][3]); 108 for(i=1;i<n;++i) 109 { 110 for(j=i+1;j<=n;++j) 111 { 112 if(judge(i,j)) 113 { 114 merge(i,j); 115 } 116 } 117 } 118 while(scanf("%d%d",&i,&j)&&(i||j)) 119 { 120 if(find(i)==find(j)) 121 printf("CONNECTED\n"); 122 else 123 printf("NOT CONNECTED\n"); 124 } 125 } 126 return 0; 127 } 128 129 130 //代码二: ----转 131 #include<stdio.h> 132 #include<math.h> 133 134 #define MAX 15 135 136 /* 定义点信息,x为横坐标,y为纵坐标 */ 137 typedef struct 138 { 139 double x; 140 double y; 141 }point; 142 143 /* 定义边信息,s为起始节点,e为终止节点 */ 144 typedef struct 145 { 146 point s; 147 point e; 148 }line; 149 150 line p[MAX]; 151 int father[MAX]; 152 int rank[MAX]; 153 154 /* 初始化集合 */ 155 void Make_Set(int x) 156 { 157 father[x] = x; 158 rank[x] = 0; 159 } 160 161 /* 查找x元素所在的集合,回溯时压缩路径 */ 162 int Find_Set(int x) 163 { 164 if (x != father[x]) 165 { 166 father[x] = Find_Set(father[x]); 167 } 168 return father[x]; 169 } 170 171 /* 合并x,y所在的集合 */ 172 void Union(int x, int y) 173 { 174 if (x == y) return; 175 if (rank[x] > rank[y]) 176 { 177 father[y] = x; 178 } 179 else 180 { 181 if (rank[x] == rank[y]) 182 { 183 rank[y]++; 184 } 185 father[x] = y; 186 } 187 } 188 189 /* 最大值函数 */ 190 double max(double x, double y) 191 { 192 return x > y ? x : y; 193 } 194 195 /* 最小值函数 */ 196 double min(double x, double y) 197 { 198 return x < y ? x : y; 199 } 200 201 /* 叉积 (a-c)x(b-c) */ 202 double multiply(point a, point b, point c) 203 { 204 return (a.x - c.x) * (b.y - c.y) - (b.x - c.x) * (a.y - c.y); 205 } 206 207 /* 跨立判断 */ 208 int intersect(line u, line v) 209 { 210 return (( max(u.s.x, u.e.x) >= min(v.s.x, v.e.x)) 211 && (max(v.s.x, v.e.x) >= min(u.s.x, u.e.x)) 212 && (max(u.s.y, u.e.y) >= min(v.s.y, v.e.y)) 213 && (max(v.s.y, v.e.y) >= min(u.s.y, u.e.y)) 214 && (multiply(v.s, u.e, u.s) * multiply(u.e, v.e, u.s) >= 0) 215 && (multiply(u.s, v.e, v.s) * multiply(v.e, u.e, v.s) >= 0)); 216 } 217 218 int main() 219 { 220 int n, i, j; 221 int a, b, x, y; 222 while(1) 223 { 224 scanf("%d", &n); 225 if (n == 0) break; 226 /* 初始化集合 */ 227 for(i = 1; i <= n; i++) 228 { 229 Make_Set(i); 230 } 231 /* 读入边信息 */ 232 for(i = 1; i <= n; i++) 233 { 234 scanf("%lf%lf%lf%lf", &p[i].s.x, &p[i].s.y, &p[i].e.x, &p[i].e.y); 235 } 236 /* 处理每条边,如果相交就合并 */ 237 for(i = 1; i <= n; i++) 238 { 239 for(j = 1; j <= n; j++) 240 { 241 if(i != j && intersect(p[i], p[j])) 242 { 243 x = Find_Set(i); 244 y = Find_Set(j); 245 Union(x,y); 246 } 247 } 248 } 249 /* 进行查询 */ 250 while(1) 251 { 252 scanf("%d %d", &a, &b); 253 if (a + b == 0) break; 254 /* 自己和自己肯定有关系 */ 255 if(a == b) 256 { 257 printf("CONNECTED\n"); 258 } 259 else 260 { 261 /* 若在一个集合则两边有关系 */ 262 x = Find_Set(a); 263 y = Find_Set(b); 264 if(x == y) 265 { 266 printf("CONNECTED\n"); 267 } 268 else 269 { 270 printf("NOT CONNECTED\n"); 271 } 272 } 273 } 274 } 275 //system("pause"); 276 return 0; 277 }
功不成,身已退