【二分图匹配】【ZJOI2009】假期的宿舍

【二分图匹配】【ZJOI2009】假期的宿舍_第1张图片

一道很裸的二分图匹配。

给每个外校学生以及每个不回家的本校学生都找一个床位,其中外校学生没有可用床位。
若所有人都能找到对应的床位,那么有可行解,否则无可行解。

要注意排除题目中的无效信息,否则它会变为错误信息。

Accode:

#include <cstdio>
#include <cstdlib>
#include <algorithm>

const int maxN = 60;

bool hvbd[maxN], gohm[maxN], marked[maxN];
//hvbd即have_bed,表示该学生是否为本校学生;
//gohm即go_home,表示该学生是否回家。
int Link[maxN], mp[maxN][maxN], n, T;

bool Find(int i)
{
    for (int j = 0; j < n; ++j)
    if (mp[i][j] && !marked[j])
    {
        marked[j] = 1;
        if (Link[j] == -1 || Find(Link[j]))
        {
            Link[j] = i;
            return 1;
        }
    }
    return 0;
}

int main()
{
    freopen("holiday.in", "r", stdin);
    freopen("holiday.out", "w", stdout);
    for (scanf("%d", &T); T; --T)
    {
        scanf("%d", &n);
        for (int i = 0; i < n; ++i)
        {
            scanf("%d", hvbd + i);
            Link[i] = -1; //由于有多组数据,注意初值。
        }
        for (int i = 0; i < n; ++i)
            scanf("%d", gohm + i);
        for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
        {
            scanf("%d", mp[i] + j);
            if (i == j) mp[i][j] = 1;
            //if (gohm[i]) mp[i][j] = 0;
	//注意上面这句话不能要,因为如果该学生为外校学生,
	//那么gohm的标记就没有意义,并且导致错误。
            if (!hvbd[j]) mp[i][j] = 0;
        }
        bool ok = 1;
        for (int i = 0; i < n; ++i)
        if (!hvbd[i] || hvbd[i] && !gohm[i])
        {
            for (int j = 0; j < n; ++j)
                marked[j] = 0; //数组清零。
            if (!Find(i))
            {
                ok = 0;
                printf("T_T\n");
                break;
            }
        }
        if (ok) printf("^_^\n");
    }
        
    return 0;
}


你可能感兴趣的:(【二分图匹配】【ZJOI2009】假期的宿舍)