IT民工
加油!

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;
}
posted on 2012-08-06 17:02  找回失去的  阅读(250)  评论(0编辑  收藏  举报