【題意】:給出n個箱子,每個箱子有三個值w,l,h。如果一個箱子的這三個值嚴格小于另一個箱子的三個值,那么可以把這個箱子放在另一個箱子里面。每個箱子里面最多只能放一個箱子,問最小情況下還有多少個箱子。

【題解】:一開始直接上排序加貪心,然后發(fā)現(xiàn)有明顯的bug。
               考慮排序后dp,發(fā)現(xiàn)是個2d的最長上升子序列,不過難以實現(xiàn)。
               無奈之下請教3x,原來是個經(jīng)典問題,最小路徑覆蓋。
               最小路徑覆蓋在二分圖上滿足:最小路徑覆蓋 = 頂點數(shù) - 最大匹配。
               由于原圖不是二分圖,需實行轉(zhuǎn)換,只需拆點即可。
               最后直接上匈牙利即可。

【代碼】:
  1 #include "iostream"
  2 #include "cstdio"
  3 #include "cstring"
  4 #include "algorithm"
  5 #include "vector"
  6 #include "queue"
  7 #include "cmath"
  8 #include "string"
  9 #include "cctype"
 10 #include "map"
 11 #include "iomanip"
 12 using namespace std;
 13 #define pb push_back
 14 #define lc(x) (x << 1)
 15 #define rc(x) (x << 1 | 1)
 16 #define lowbit(x) (x & (-x))
 17 #define ll long long
 18 #define maxn 1500 
 19 #define maxm 1000500
 20 int n;
 21 int eh[maxn], tot;
 22 bool visit[maxn];
 23 int match[maxn];
 24 
 25 struct Edge {
 26     int u, v, next;
 27 }et[maxm];
 28 
 29 struct Point {
 30     int w, l, h;
 31 }p[maxn];
 32 
 33 void init() {
 34     tot = 0;
 35     memset(eh, -1, sizeof(eh));
 36 }
 37 
 38 void addedge(int u, int v) {
 39     Edge e = {u, v, eh[u]};
 40     et[tot] = e;
 41     eh[u] = tot++;
 42 }
 43 
 44 bool dfs(int u) {
 45     for(int i = eh[u]; i != -1; i = et[i].next) {
 46         int v = et[i].v;
 47         if (!visit[v]) {
 48             visit[v] = true;
 49             if (match[v] == -1 || dfs(match[v])) {
 50                 match[v] = u;
 51                 return true;
 52             }
 53         }
 54     }
 55     return false;
 56 }
 57 
 58 int Match() {//二分圖匹配
 59     int cnt = 0;
 60     memset(match, -1, sizeof (match));
 61     for (int u = 1; u <= 2 * n; u++) {
 62         memset(visit, falsesizeof (visit));
 63         if (dfs(u)) cnt++; //每找到一條增廣路,匹配數(shù)+1
 64     }
 65     return cnt; //返回最大匹配數(shù)
 66 }
 67 
 68 bool check(const Point &a, const Point &b) {
 69     return a.h < b.h && a.l < b.l && a.w < b.w;
 70 }
 71 
 72 void build() {
 73     init();
 74     for(int i = 0; i < n; i++) {
 75         for(int j = 0; j < n; j++) {
 76             if(check(p[i], p[j])) addedge(i + n, j);
 77         }
 78     }
 79 }
 80 
 81 int main() {
 82     while(~scanf("%d", &n) && n) {
 83         for(int i = 0; i < n; i++) scanf("%d%d%d", &p[i].w, &p[i].l, &p[i].h);
 84         build();
 85         printf("%d\n", n - Match());
 86     }
 87     return 0;
 88 }