P2055 [ZJOI2009]假期的宿舍

题目意思是  给定n个人 其中有人有床 有人没床  有床的人中有人离开

每个人都只能使用自己直接认识的人的床 询问剩下的人是否都能有床使用

(一个床只能被一个人使用)

不难看出

利用匈牙利算法进行二分图匹配

只有达到完美匹配才合法

注意每组数据初始化

#include
#include
using namespace std;
int T,n,lnk[101][101],p[101],flag[100],flagx[101],x,flagz;
bool vis[101];
int read()
{
    int xv=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') xv=xv*10+ch-'0',ch=getchar();
    return xv;
}
bool DFS(int x)
{
    for(int j=1;j<=lnk[x][0];j++)//寻找可以连的床 
	if(!vis[lnk[x][j]]&&flag[lnk[x][j]])//如果没被匹配
	{
        vis[lnk[x][j]]=1;
        if(!p[lnk[x][j]]||DFS(p[lnk[x][j]]))
        //如果这一床没被匹配或存在增广路 
		{p[lnk[x][j]]=x;return 1;}
    }
    return 0;
}
int main()
{
	T=read();
	while(T--)
	{
		memset(lnk,0,sizeof(lnk));
		memset(flag,0,sizeof(flag));
		memset(flagx,0,sizeof(flagx));
		memset(p,0,sizeof(p));
		n=read();
		for(int i=1;i<=n;i++)flag[i]=read();
		//flag[i]为真表示i是住校生 
		for(int i=1;i<=n;i++)x=read(),flagx[i]=flag[i]?x:-1;
		//flagx[i]  1:回家(有空床)  0:不回家(自己有床)  -1:来拜访(没床) 
		for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
		{
			x=read();if(flagx[i]==1)continue;
			//走了的人就不需要连床 
			if(x)lnk[i][++lnk[i][0]]=j;
			//如果和床主人认识 连床 
			if(i==j&&flag[i]==1)lnk[i][++lnk[i][0]]=j;
			//自己有自己的床 
		}
		flagz=1;
        for(int i=1;i<=n;i++)
        if(flagx[i]!=1)//需要有床 
		{
            memset(vis,0,sizeof vis);
            if(!DFS(i))//如果人没被匹配上
			{puts("T_T"),flagz=0;break;}
        }
        if(flagz) puts("^_^");
	}
}

 

你可能感兴趣的:(难堪大用)