题目描述:
给出N平行于坐标轴的线段,要你选出尽量多的线段使得这些线段两两没有交点(顶点也算),横的与横的,竖的与竖的线段之间保证没有交点,输出最多能选出多少条线段。
因为横的与横的,竖的与竖的没有交点,所以直接把相交的线段相连,然后肯定是个二分图。
选出多少个线段,就是求二分图的最大独立集,等于节点数(N) - 最大匹配数。
由于线段的4个坐标太大 (X1_i, Y1_i) and (X2_i, Y2_i) (1 <= X1_i, Y1_i, X2_i, Y2_i <= 1,000,000,000),不能用二维矩阵来记录。
又看到线段数量很少 (1 <= N <= 250),所以可以用结构体来存,然后通过两重循环判断线段是否相连。
——代码

1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 5 using namespace std; 6 7 int n, lh, ll, cnt, sum; 8 int next[62501], to[62501], head[251], g[251]; 9 bool vis[251]; 10 struct node 11 { 12 int pos, minn, maxx; 13 }h[10001], l[10001]; 14 15 void add(int x, int y) 16 { 17 to[cnt] = y; 18 next[cnt] = head[x]; 19 head[x] = cnt++; 20 } 21 22 bool check(int i, int j) 23 { 24 if(h[i].pos < l[j].minn || h[i].pos > l[j].maxx) return 0; 25 if(l[j].pos < h[i].minn || l[j].pos > h[i].maxx) return 0; 26 return 1; 27 } 28 29 bool find(int u) 30 { 31 int i, v; 32 for(i = head[u]; i != -1; i = next[i]) 33 { 34 v = to[i]; 35 if(!vis[v]) 36 { 37 vis[v] = 1; 38 if(!g[v] || find(g[v])) 39 { 40 g[v] = u; 41 return 1; 42 } 43 } 44 } 45 return 0; 46 } 47 48 int main() 49 { 50 int i, j, x1, y1, x2, y2; 51 scanf("%d", &n); 52 memset(head, -1, sizeof(head)); 53 for(i = 1; i <= n; i++) 54 { 55 scanf("%d %d %d %d", &x1, &y1, &x2, &y2); 56 if(x1 == x2) 57 { 58 ++lh; 59 h[lh].pos = x1; 60 h[lh].minn = min(y1, y2); 61 h[lh].maxx = max(y1, y2); 62 } 63 else if(y1 == y2) 64 { 65 ++ll; 66 l[ll].pos = y1; 67 l[ll].minn = min(x1, x2); 68 l[ll].maxx = max(x1, x2); 69 } 70 } 71 for(i = 1; i <= lh; i++) 72 for(j = 1; j <= ll; j++) 73 if(check(i, j)) 74 add(i, j); 75 for(i = 1; i <= lh; i++) 76 { 77 memset(vis, 0, sizeof(vis)); 78 if(find(i)) sum++; 79 } 80 printf("%d", n - sum); 81 return 0; 82 }