POJ 1469 COURSES

本文介绍了一种使用匈牙利算法解决最大匹配问题的方法。通过两个学生的例子,展示了如何为一系列课程寻找最佳匹配的学生,确保每个学生恰好匹配一门课程,且所有课程都被覆盖。代码实现采用C++,并提供了两种不同的实现方式。

 

      这道题要我们找到p门课和n个学生是否存在一种关系,即在一个集合中的学生,

每人代表一门课,每门课在这个集合中也有一个代表。求的的最大匹配数是否等于课程总数。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#define MAXN 305

bool map[105][MAXN], vis[MAXN];
int link[MAXN];
int p, n;

bool dfs(int u)
{
int v;
for( v = 1; v <= n; v++)
if( map[u][v] && !vis[v])
{
vis[v]=true;
if( link[v] == -1 || dfs(link[v]) )
{
link[v] = u;
return true;
}
}
return false;
}

int main()
{
int cas, u, k, v, ans;
scanf("%d", &cas);
while( cas--)
{
memset( map, false, sizeof(map));
scanf("%d%d", &p, &n);
for( u = 1; u <= p; u++)
{
scanf("%d", &k);
while( k--)
{
scanf("%d", &v);
map[u][v]=true;
}
}
ans = 0;
memset( link, -1, sizeof(link) );
for( u = 1; u <= p; u++)
{
memset( vis, false, sizeof(vis) );
if(dfs(u)) ans++;
}
if( ans == p)
printf("YES\n");
else printf("NO\n");

}
return 0;
}

  看了CSGrandeur大牛的代码,我们得到了另一种方法,同样是匈牙利算法,我们只需将MaxMatch函数做一定改变,

给每一个课程u找匹配,当有一个u找不到与之匹配的学生v,就返回false,代码如下:

/*Accepted 200K 438MS C++ 1048B 2012-04-14 10:45:47 */

#include<cstdio>
#include<cstring>
#include<cstdlib>

const int MAXP = 105, MAXN = 305;
bool g[MAXP][MAXN], chk[MAXN];
int xM[MAXP], yM[MAXN];
int p, n;

bool SearchPath( int u) {
    int v;
    for( v = 1; v <= n; v ++)
        if( g[u][v] && !chk[v])
        {
            chk[v] = true;
            if( yM[v] == -1 || SearchPath( yM[v]) )
            {
                yM[v] = u; xM[u] = v;
                return true;
            }
        }
    return false;
}

bool MaxMatch()
{
    int u;
    memset( xM, -1, sizeof xM);
    memset( yM, -1, sizeof yM);
    for( u = 1; u <= p; u ++ )
        if( xM[u] == -1) {
            memset( chk, false, sizeof chk);
            if( !SearchPath(u) ) return false;
        }
    return true;
}

void Read_Gragh()
{
    scanf( "%d%d", &p, &n);
    int t;
    memset( g, false, sizeof g);
    for( int i = 1; i <= p; i ++)
    {
        scanf( "%d", &t);
        while( t --)
        {
            int j;
            scanf( "%d", &j);
            g[i][j] = true;
        }
    }
}

int main()
{
    int T;
    scanf( "%d", &T);
    while( T --)
    {
         Read_Gragh();
         if( MaxMatch() ) printf( "YES\n");
         else printf( "NO\n");
    }
    return 0;
}

 

 

 

 

转载于:https://www.cnblogs.com/Yu2012/archive/2012/04/03/2431398.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值