BZOJ1433&&洛谷P2055

中文体面不再翻译,通过画图我们可以知道只是一道二分图匹配,那么如何进行匹配呢,我们要存一下,在校学生和外校学生的编号,然后走掉的人当床位,认识的人连边,用住校生和外校生与床位跑二分图匹配,做到这里,你大概能get到70%的分数,因为你没有考虑全面问题,还有一个必须考虑的条件是最大匹配数要等于需要匹配的人数,不然就有人无法睡觉233

代码

#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=500;
int t,n,m;
int tot,cnt,ans;
int a[M],b[M],c[M];
int map[M][M],mat[M],vis[M];
vector<int>v[M<<2];
int mid(int x)
{
    for(int i=0;i<v[x].size();i++)
    {
        int go=v[x][i];
        if (vis[go]) continue;;
        vis[go]=1;
        if(!mat[go]||mid(mat[go]))
        {
            mat[go]=x;
            return 1;
        }
    }
    return 0;
}
void clear()
{
    memset(a,0,sizeof(a));memset(b,0,sizeof(b));
    memset(c,0,sizeof(c));memset(mat,0,sizeof(mat));
    memset(map,0,sizeof(map));
    for (int i=1;i<=n;i++)
     	v[i].clear();
    return ;
}
void clean()
{
    memset(vis,0,sizeof(vis));
    return ;
}
void built()
{
    for (int i=1;i<=cnt;i++)
    for (int k=1;k<=tot;k++)
    if (map[c[k]][b[i]]) v[b[i]].push_back(c[k]);
}
int main()
{
    cin>>t;
    while (t--)
    {
        scanf("%d",&n);cnt=ans=tot=0;clear();
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&m);
            if(a[i])
            {
                if(m) c[++tot]=i;
                else b[++cnt]=c[++tot]=i;
            }
            else b[++cnt]=i;
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                cin>>map[i][j];
        for(int i=1;i<=n;i++)
            if(a[i]) map[i][i]=1;
        built();
        for(int i=1;i<=cnt;clean(),i++)
            if(mid(b[i])) ans++;
        if(cnt>tot) ans=-1;     
        if(ans==cnt) cout<<"^_^"<<endl;
        else cout<<"T_T"<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/acerandaker/article/details/80714104