P2055 [ZJOI2009]假期的宿舍(二分图匹配)

满分做法:

把人向床连边进行二分图匹配即可。

#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
typedef long long ll;
const int maxm=5555;
int t,n,ans;
int school[maxm],home[maxm];
int pre[maxm],last[maxm],other[maxm],l; 
int match[maxm];
bool vis[maxm];
void add(int x,int y)
{
 l++;
 pre[l]=last[x];
 last[x]=l;
 other[l]=y;	
}
bool dfs(int x)
{
 for(int p=last[x];p;p=pre[p])
 {
  int v=other[p];
  if(vis[v]) continue;
  vis[v]=1;
  if(match[v]==-1||dfs(match[v]))
  {
    match[v]=x;
	return 1;	
  }
 }
 return 0;
}
void dfs_xyl()
{
 memset(match,-1,sizeof(match));
 for(int i=1;i<=n;i++)
 {
  if(!school[i]||(school[i]&&!home[i]))
  {
    memset(vis,0,sizeof(vis));
    if(dfs(i))
    {
     ans++;	
    }
  }
 }
}
int main()
{
 scanf("%d",&t);
 while(t--)
 {
  memset(last,0,sizeof(last)); 
  int tot=0;
  ans=0;
  scanf("%d",&n);
  for(int i=1;i<=n;i++)
  scanf("%d",&school[i]);
  for(int i=1;i<=n;i++)
  {
   scanf("%d",&home[i]);
   if(school[i]&&!home[i])
   add(i,i);
  }
  for(int i=1;i<=n;i++)
  if(!school[i]||(school[i]&&!home[i])) tot++;
  for(int i=1;i<=n;i++)
  {
   for(int j=1;j<=n;j++)
   {
     int x;
     scanf("%d",&x);
     if(x&&school[j])
     add(i,j);
   }
  }
  dfs_xyl();
  if(ans!=tot)
  printf("T_T\n");
  else  printf("^_^\n");
 }
 return 0;	
}
posted @ 2019-10-17 20:45  lihan123  阅读(93)  评论(0编辑  收藏  举报