传送门:http://www.usaco.org/index.php?page=viewproblem2&cpid=93
很容易发现,这是一个二分图的模型。竖直线是X集,水平线是Y集,若某条竖直线与水平线相交,则连边。由于目的是要没有任何两条线相交,所以二分图的边的两端不能同时取,就是要求一个二分图的最大独立集,which equals to N - 最大匹配。
然而啊然而,仍然没有一A!此题只是说给出线段两端点的坐标,并没有说x1一定<x2,y1一定<y2。。。
可以说这是本次月赛金足最水的题,竟然放在第三题,吃鲸。。。
#include <cstdio> #include <cstring> const int maxn = 255; int link[maxn], n, idxx, idxy, match, tem; bool cover[maxn], g[maxn][maxn]; struct st { int x1, y1, x2, y2; } x[maxn], y[maxn], t; bool fnd(int i) { for (int j = 1; j <= idxy; ++j) { if (!cover[j] && g[i][j]) { cover[j] = 1; if (!link[j] || fnd(link[j])) { link[j] = i; return true; } } } return false; } int main(void) { freopen("steeple.in", "r", stdin); freopen("steeple.out", "w", stdout); scanf("%d", &n); for (int i = 0; i < n; ++i) { scanf("%d%d%d%d", &t.x1, &t.y1, &t.x2, &t.y2); if (t.x1 == t.x2) { if (t.y1 > t.y2) { tem = t.y1; t.y1 = t.y2; t.y2 = tem; } x[++idxx] = t; } else { if (t.x1 > t.x2) { tem = t.x1; t.x1 = t.x2; t.x2 = tem; } y[++idxy] = t; } } for (int i = 1; i <= idxx; ++i) { for (int j = 1; j <= idxy; ++j) { if (x[i].x1 >= y[j].x1 && x[i].x1 <= y[j].x2 && y[j].y1 >= x[i].y1 && y[j].y1 <= x[i].y2) { g[i][j] = 1; } } } for (int i = 1; i <= idxx; ++i) { memset(cover, 0, sizeof cover); if (fnd(i)) { ++match; } } printf("%d ", n - match); return 0; }
(ps,我写比较长的函数的时候总是在最后忘记return,导致一些奇奇怪怪的错误,以后我需要强制自己写完签名后立即写上return啥!)