題目大意是依次給出線段,如果詢問第k條給出的線段就輸出與第k條線段直接相交和間接相交的所有線段條數(注意包含他本身,所以num初始化為1)
典型判斷相交,用並查集
My Code有個地方wa了我好久,就是在函數中,如果交換參數的值,注意參數如果是指標類型的,導致調用該函數的外部函數中的資料也交換了影響程式結果(看注釋)
My Code:
#include<stdio.h>#include<string.h>int father[1001];int num[1001];double line[1001][2][2];int n, q;double Min(double a, double b){return a < b ? a : b;}double Max(double a, double b){return a > b ? a : b;}bool equal(double a, double b){return a == b;}bool between(double a, double b, double c){if(a <= Max(b, c) && a >= Min(b, c))return 1;return 0;}int swap(double line1[][2], double line2[][2]){int i, j;double temp;for(i = 0; i < 2; i ++)for(j = 0; j < 2; j ++){temp = line1[i][j];line1[i][j] = line2[i][j];line2[i][j] = temp;}return 0;}bool cut(double line1[][2], double line2[][2]) //判斷相交{double k1,k2, b1, b2, x, y;if(equal(line2[0][0], line2[1][0])) //如果存在沒有斜率的情況,就讓函數進入下面的if語句中,但是這樣交換卻使全域line中的線段序號發生了變化{swap(line1, line2); //所以我在main中對兩個線段都進行了複製}if(equal(line1[0][0], line1[1][0])) //沒有斜率情況{if(equal(line2[0][0], line2[1][0])){if(equal(line1[0][0], line2[0][0]) && (between(line1[0][1], line2[0][1], line2[1][1]) || between(line1[1][1], line2[0][1], line2[1][1])|| between(line2[0][1], line1[0][1], line1[1][1]) || between(line2[1][1], line1[0][1], line1[1][1])))return 1;else{return 0;}}else{k2 = (line2[1][1] - line2[0][1]) / (line2[1][0] - line2[0][0]);b2 = line2[1][1] - k2 * line2[1][0];if(!between(line1[0][0], line2[0][0], line2[1][0]))return 0;y = k2 * line1[0][0] + b2;if(between(y, line1[0][1], line1[1][1]) && between(y, line2[0][1], line2[1][1]))return 1;elsereturn 0;}}k1 = (line1[1][1] - line1[0][1]) / (line1[1][0] - line1[0][0]);b1 = line1[1][1] - k1 * line1[1][0];k2 = (line2[1][1] - line2[0][1]) / (line2[1][0] - line2[0][0]);b2 = line2[1][1] - k2 * line2[1][0];if(k1 - k2 == 0 && (between(line1[0][0], line2[0][0], line2[1][0]) || between(line1[1][0], line2[0][0], line2[1][0])|| between(line2[0][0], line1[0][0], line1[1][0]) || between(line2[1][0], line1[0][0], line1[1][0])))return 1;x = (b2 - b1) / (k1 - k2);y = x * k1+ b1;if(between(y, line1[0][1], line1[1][1]) && between(y, line2[0][1], line2[1][1])&& between(x, line1[0][0], line1[1][0]) && between(x, line2[0][0], line2[1][0]))return 1;return 0; }int init(){int i;n = 0;for(i = 1; i <= 1000; i ++){father[i] = i;num[i] = 1;}return 0;}int find(int x){if(father[x] == x)return x;return father[x] = find(father[x]);}int uni(int a, int b){int afa = find(a), bfa = find(b);if(afa == bfa)return 0;num[afa] += num[bfa];father[bfa] = afa;return 0;}int copy(double line1[][2], double line2[][2]){int i, j;for(i = 0; i < 2; i ++)for(j = 0; j < 2; j ++){line1[i][j] = line2[i][j];}return 0;}int main(){int cases, i, k;char str[2];double temp1[2][2];double temp2[2][2];scanf("%d", &cases);while(cases --){scanf("%d", &q);init();while(q --){scanf("%s", str);if(str[0] == 'P'){n ++;scanf("%lf%lf%lf%lf", &line[n][0][0], &line[n][0][1], &line[n][1][0], &line[n][1][1]);for(i = 1; i < n; i ++){copy(temp1, line[n]);//進行複製,避免交換copy(temp2, line[i]);//進行複製,避免交換if(cut(temp1, temp2))uni(i, n);}}else{scanf("%d", &k);printf("%d\n", num[find(k)]);}}if(cases != 0)printf("\n");}return 0;}
以後一定要留個心眼,就是在函數對參數進行交換的時候