首页 > 代码库 > bzoj1433[ZJOI2009]假期的宿舍(匈牙利)

bzoj1433[ZJOI2009]假期的宿舍(匈牙利)

 

1433: [ZJOI2009]假期的宿舍

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 2544  Solved: 1074

[Submit][Status][Discuss]

Description

技术分享

Input

技术分享

Output

技术分享

Sample Input

1
3
1 1 0
0 1 0
0 1 1
1 0 0
1 0 0

Sample Output

ˆ ˆ

HINT

对于30% 的数据满足1 ≤ n ≤ 12。
对于100% 的数据满足1 ≤ n ≤ 50,1 ≤ T ≤ 20。

 

 
/*看这个题,不难发现是二分图,裸的匈牙利。 也很好想到要把人和床分开建图。 但是容易吧不在校的和在校的人分开。其实不该分开,建图是没有任何影响的有一点要注意,很容易忽略把在校的人和自己的床建边,忘了就WA了!预处理稍麻烦。 */ #include<iostream>#include<cstdio>#include<cstring>#define maxn 101using namespace std;int T,n,m,k,ans,cnt1,cnt2;int bed[maxn],vis[maxn],Link[maxn],Judge[maxn],people[maxn];int a[maxn][maxn];inline int insert(){    int x=0,f=1;char c=getchar();    while(c>9||c<0){if(c==-)f=-1;c=getchar();}    while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}    return x*f;}inline void first(){    ans = 0;    memset(a,0,sizeof(a));    memset(bed,0,sizeof(bed));    memset(Judge,0,sizeof(Judge));    memset(people,0,sizeof(people));    memset(Link,0,sizeof(Link));    cnt1=cnt2=0;}bool hungarian(int x){    for(int i=1;i<=cnt1;i++)    {        if(a[x][bed[i]]&&!vis[bed[i]])        {            vis[bed[i]]=1;            if(!Link[bed[i]]||hungarian(Link[bed[i]]))            {                Link[bed[i]]=x;                return true;            }        }    }    return false;}int main(){    T=insert();    while(T--)    {        first();        n=insert();        for(int i=1;i<=n;i++)          Judge[i]=insert();        for(int i=1;i<=n;i++)        {            int tmp;            tmp=insert();            if(Judge[i])            {                if(tmp) bed[++cnt1]=i;//不在校的                 else bed[++cnt1]=people[++cnt2]=i;//在校的             }            else people[++cnt2]=i;//来探望的         }        for(int i=1;i<=n;i++)          for(int j=1;j<=n;j++)            a[i][j]=insert();        for(int i=1;i<=n;i++)          if(Judge[i]) a[i][i]=1;//自己的床          for(int i=1;i<=cnt2;i++)         {             memset(vis,0,sizeof(vis));             if(hungarian(people[i]))//if后面又打成了分号,罚自己中午多吃一个馒头2333                ans++;         }          if(cnt2>cnt1) ans=-1;         if (ans == cnt2)            printf("^_^\n");         else            printf("T_T\n");    }    return 0;}

 

 
[

bzoj1433[ZJOI2009]假期的宿舍(匈牙利)