【bzoj1059】[ZJOI2007]矩阵游戏

2015.05.28 17:04 Thu | 26次阅读 | 旧日oi | 固定链接 | 源码

Description

小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏——矩阵游戏。矩阵游戏在一个N*N黑白方阵进行(如同国际象棋一般,只是颜色是随意的)。每次可以对该矩阵进行两种操作:行交换操作:选择矩阵的任意两行,交换这两行(即交换对应格子的颜色)列交换操作:选择矩阵的任意行列,交换这两列(即交换对应格子的颜色)游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑色。对于某些关卡,小Q百思不得其解,以致他开始怀疑这些关卡是不是根本就是无解的!!于是小Q决定写一个程序来判断这些关卡是否有解。
n,m<=200

题解

我们可以发现,每行最多只有1个点有用,同理每列也是一样,而只要每一行能唯一的对应上一个列,那么就一定能构造出方案。所以我们可以想到二分图,每一行可以和这行中颜色为1的列匹配,如果最后能完全匹配,说明有解。
话说自己很少能想到二分图的模型……所以这次自己yy出来很开心~

我的程序

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,T,tim,ans;
int mp[205][205],vis[205],match[205];
int dfs(int u)
{
    for(int i=1;i<=n;i++)
    if(mp[u][i]&&vis[i]!=tim)
    {
        vis[i]=tim;
        if(!match[i]||dfs(match[i]))
        {
            match[i]=u;
            return 1;
        }
    }
    return 0;
}
int main()
{
    cin>>T;
    while(T--)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        scanf("%d",&mp[i][j]);
        memset(vis,-1,sizeof(vis));
        memset(match,0,sizeof(match));
        ans=tim=0;
        for(int i=1;i<=n;i++,tim++)
        if(dfs(i)) ans++;
        if(ans==n) puts("Yes");
        else puts("No");
    }
    return 0;
}```