刷题记录-luoguP2055 [ZJOI2009]假期的宿舍

来源:互联网 发布:图像算法工程起薪 编辑:程序博客网 时间:2024/05/17 12:02

对于学生和床,可以看成是二分图,让尽可能多的学生能睡到床上,可以看成二分图的最大匹配

对于本校学生,自己可以睡自己的床和认识的人的床,我们连一条边

对于外校学生,可以睡认识的人的床,我们连一条边

然后跑一边匈牙利算法就AC啦

*********************************************

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#define MAXV 55
#define MAXE 55*55*2
using namespace std;
int V,E;
int bf[MAXV];
int check[MAXV];
int first[MAXV],nextt[MAXE],to[MAXE];
int sch[MAXV],home[MAXV];
int found(int x){
    for(int e=first[x];e;e=nextt[e]){
        int y=to[e];
        if(!check[y]){
            check[y]=1;
            if(!bf[y]||found(bf[y])){
                bf[y]=x;
                return 1;
            }
        }
    }
    return 0;
}
void add(int x,int y){
    E++;
    nextt[E]=first[x];
    first[x]=E;
    to[E]=y;
}
int solve(){
    memset(bf,0,sizeof(bf));
    memset(check,0,sizeof(check));
    memset(first,0,sizeof(first));
    memset(nextt,0,sizeof(nextt));
    memset(to,0,sizeof(to));
    memset(sch,0,sizeof(sch));
    memset(home,0,sizeof(home));
    scanf("%d",&V);
    E=0;
    for(int i=1;i<=V;i++){
        scanf("%d",&sch[i]);
    }
    for(int i=1;i<=V;i++){
        scanf("%d",&home[i]);
    }
    for(int i=1;i<=V;i++){
        for(int j=1;j<=V;j++){
            int temp;
            scanf("%d",&temp);
            if((temp||i==j)&&sch[j]){
                add(i,j);
            }
        }
    }
    for(int i=1;i<=V;i++){
        if((sch[i]&&!home[i])||!sch[i]){
            memset(check,0,sizeof(check));
            if(!found(i)){
                return 0;
            }
        }
    }
    return 1;
}
int main()
{
//    freopen("data.in","r",stdin);
//    freopen("my.out","w",stdout);
    int T;
    scanf("%d",&T);
    while(T--){
        if(solve()){
            printf("^_^\n");
        }
        else{
            printf("T_T\n");
        }
    }
    return 0;
}

原创粉丝点击