[題解]luogu_P2055假期的宿舍(二分圖最大匹配)

雖然是裸題但是仍然沒有看出來......


 

1.每個人都對應一張床(可以的話),這樣把人和床看成點,對應關係就是邊,跑最大匹配看匹配數量夠不夠即可

2.連邊條件:如果一個學生且不回家,那麼他可以睡自己的床,向自己的床連邊

如果外來人且認識一個回家學生,那麼他可以睡學生的床,向學生的床連邊

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100;
int T,n;
struct node{
    int v,nxt;
}e[10000];
int head[maxn],cnt,tot,sum;
int hom[maxn],sch[maxn];
int match[maxn];
bool v[maxn];
void add(int u,int v){
    e[++cnt].v=v;e[cnt].nxt=head[u];head[u]=cnt;
}

bool dfs(int x){
    for(int i=head[x];i;i=e[i].nxt){
        int y=e[i].v;
        if(!v[y]){
            v[y]=1;
            if(!match[y] || dfs(match[y])){match[y]=x;return 1;}
        }
    }
    return 0;
}
int main()
{
    scanf("%d",&T);
    while(T--){
        cnt=tot=sum=0;
        memset(head,0,sizeof(head));
        memset(match,0,sizeof(match));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        scanf("%d",&sch[i]);
        for(int i=1;i<=n;i++){
            scanf("%d",&hom[i]);
            if(hom[i]==0 && sch[i])add(i,i);//在校不回家可以睡自己的床 
        }
        for(int i=1;i<=n;i++)
        if(!sch[i] || (sch[i] && !hom[i]))//需要床的人 
        tot++;
        for(int i=1,a;i<=n;i++)
        for(int j=1;j<=n;j++){
            scanf("%d",&a);if(a && sch[j])add(i,j);//i認識j並且j是學生 
        }
        for(int i=1;i<=n;i++)
        if((sch[i] && hom[i]==0) || !sch[i]){//學生在學校或外來人 
            memset(v,0,sizeof(v));
            if(dfs(i))sum++;
        }
        if(sum==tot)printf("^_^\n");
        else printf("T_T\n");
    }
}

 

posted @ 2019-04-17 17:56  羊肉汤泡煎饼  阅读(123)  评论(0编辑  收藏  举报