http://poj.org/problem?id=1325
做的第一道二分图匹配的题,应该说代码是很基础的,但是建模确实需要一定的技巧。
这也是黑书上的一个例题,将每个任务看成一条边,把A机器的每个模式看成一个X结点,
B机器的看成Y结点。任务i为( ai, bj)。这道题求的是最少的点,让每条边都至少与其中
一个点关联。这里有一个结论,这个最少点数就是最大匹配数M,黑书的证明如下:
(1) M个是足够的。只需要让它们覆盖最大匹配的这M条边,则其他边一定被覆盖
(如果有一条边e不被覆盖,把e加入后得到一个更大的匹配)
(2) M个是必需的。仅仅考虑形成最大匹配的这M条边,由于它们两两无公共点,
因此至少要M个点才能把它们覆盖。
/*Accepted 132K 32MS C++ 1207B 2012-08-06 17:01:24*/ #include<string.h> #include<stdio.h> #include<stdlib.h> const int MAXD = 110; int n, m, k; bool map[MAXD][MAXD], vis[MAXD]; int yM[MAXD], xM[MAXD]; bool dfs( int u) { int v; for( v = 0; v < m; v ++) if( map[u][v] && !vis[v]) { vis[v] = true; if( yM[v] == -1 || dfs( yM[v])) { yM[v] = u, xM[u] = v; return true; } } return false; } int MaxMatch() { int u, ret = 0; memset( xM, -1, sizeof xM); memset( yM, -1, sizeof yM); for( u = 0; u < n; u ++) { if( xM[u] == -1) { memset( vis, false, sizeof vis); if( dfs(u)) ret ++; } } return ret; } int main() { while( scanf( "%d", &n), n) { if( n == 0) break; scanf( "%d%d", &m, &k); memset( map, false, sizeof map); for( int i = 0; i < k; i ++) { int task, x, y; scanf( "%d%d%d", &task, &x, &y); if( x * y != 0) map[x][y] = true; } int ans = MaxMatch(); printf( "%d\n", ans); } return 0; }