首页 > 其他 > 详细

BZOJ 1059 [ZJOI2007]矩阵游戏

时间:2015-02-26 20:19:33      阅读:300      评论:0      收藏:0      [点我收藏+]

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1059

题意:给定一个n * n的01矩阵,可以任意交换两行或两列的数字,问是否能调整出一个局面,使得矩阵的主对角线(左上角到右下角的连线)上都是1。n200

题解:
由于每次可以变化一些元素为1的点的行号与列号,但是其相对位置是不变的,也就是说对于(i,j)的元素,经过变换之后是(ai,bj){an}{bn}1n的排列,所以我们可以抛弃这些点的行号与列号来分析他们的相对关系。
目标局面是(i,i)的元素为1,即存在n个元素为1的点使得对于每个点(i,j)ai=bj,这可以看作是第i行与第j列匹配,而(i,j)处元素为1则代表第i列与第j列可以匹配。
题目转化为二分图匹配,每一行匹配一列,均能成功匹配则存在调整方案,时间复杂度O(n3)

代码:

#include <cstdio>
#include <cstring>
const int maxn = 201;
int n, mark[maxn];
bool vis[maxn][maxn], y[maxn];
bool find(int x)
{
    for(int i = 1; i <= n; ++i)
        if(vis[x][i] && !y[i])
        {
            y[i] = 1;
            if(!mark[i] || find(mark[i]))
            {
                mark[i] = x;
                return 1;
            }
        }
    return 0;
}
bool check()
{
    for(int i = 1; i <= n; ++i)
    {
        memset(y, 0, sizeof y);
        if(!find(i)) return 0;
    }
    return 1;
}
int main()
{
    int t;
    scanf("%d", &t);
    while(t--)
    {
        memset(vis, 0, sizeof vis);
        memset(mark, 0, sizeof mark);
        scanf("%d", &n);
        for(int i = 1, x; i <= n; ++i)
            for(int j = 1; j <= n; ++j)
            {
                scanf("%d", &x);
                if(x) vis[i][j] = 1;
            }
        puts(check() ? "Yes" : "No");
    }
    return 0;
}

BZOJ 1059 [ZJOI2007]矩阵游戏

原文:http://blog.csdn.net/skywalkert/article/details/43955739

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!