BZOJ1433/ZJOI2009/假期的宿舍

Posted on By 二价氢

我们可以把点分为两类

一类是要♂床♂睡的,一类是提供床的(话说不就是个床铺问题么?两个人睡一张床也没问题的吧(啊!好大~)!如果B看A但是性别不同怎么办?这题问题太多了!)

貌似又扯到奇怪的事情上去了23333

然后跑个二分图匹配就好了,正好试试匈牙利算法~

样例所对应的图

AC-Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
const int maxn=75;
vector<int> v[maxn];
typedef vector<int>::iterator it;
int bed[maxn],need[maxn],mat[maxn],use[maxn],n,totneed;
void reset()
{
    for (int i=1;i<maxn;i++)
        v[i].clear();
    memset(bed,0,sizeof(bed));
    memset(need,0,sizeof(need));
    memset(mat,0,sizeof(mat));
    memset(use,0,sizeof(use));
    n=totneed=0;
}
int find(int x)
{
    for (it i=v[x].begin();i!=v[x].end();i++)
    {
        if (!use[*i]&&bed[*i])
        {
            use[*i]=1;
            if (mat[*i]==0||find(mat[*i]))
            {
                mat[*i]=x;
                return 1;
            }
        }
    }
    return 0;
}
int xyl()
{
    int match=0;
    for (int i=1;i<=n;i++)
    {
        if (!need[i])
        {
            memset(use,0,sizeof(use));
            match+=find(i);
        }
    }
    return match;
}
void work()
{
    reset();
    int t;
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&need[i]);
        bed[i]=need[i];
    }
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&t);
        if (bed[i]&&!t)
            need[i]=0;
        if (!need[i])
            totneed++;
    }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
        {
            scanf("%d",&t);
            if (t||(i==j))
                v[i].push_back(j);
        }
    if (xyl()==totneed)
        printf("^_^\n");
    else
        printf("T_T\n");
}
int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
        work();
    return 0;
}