POJ 1325 Machine Schedule

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;

}

你可能感兴趣的:(schedule)