Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 2624 | Accepted: 1183 |
Description
Input
Output
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 }