zoukankan      html  css  js  c++  java
  • bzoj1059 [ZJOI2007]矩阵游戏

    1059: [ZJOI2007]矩阵游戏

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 4934  Solved: 2360
    [Submit][Status][Discuss]

    Description

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

    Input

      第一行包含一个整数T,表示数据的组数。接下来包含T组数据,每组数据第一行为一个整数N,表示方阵的大
    小;接下来N行为一个N*N的01矩阵(0表示白色,1表示黑色)。

    Output

      输出文件应包含T行。对于每一组数据,如果该关卡有解,输出一行Yes;否则输出一行No。

    Sample Input

    2
    2
    0 0
    0 1
    3
    0 0 1
    0 1 0
    1 0 0

    Sample Output

    No
    Yes
    【数据规模】
    对于100%的数据,N ≤ 200
    分析:二分图匹配的经典模型啊。
          显然只要有n个不同行也不同列的点,就一定有解!考虑二分图匹配,把行放在左边,列放在右边,如果i行j列有一个1,那么从i向j连一条有向边。如果最大匹配数=n,那么就一定有解,否则无解.
    具体的原理是第i行如果与多个列有边相连,根据匹配的原则只能选一条边,这就保证了不会出现同一行和同一列的点,正好选了n个点就匹配成功了,那么就有解了.
          关于二分图匹配的模型,推荐文章:传送门
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cmath>
    #include<map>
    
    using namespace std;
    
    const int inf = 0x7ffffff;
    
    int T,n,a[210][210],vis[210],pipei[210],res;
    
    bool find(int x)
    {
        for (int i = 1; i <= n; i++)
        {
            if (a[x][i] && !vis[i])
            {
                vis[i] = 1;
                if (!pipei[i] || find(pipei[i]))
                {
                    pipei[i] = x;
                    return true;
                }
            }
        }
        return false;
    }
    
    int main()
    {
        scanf("%d", &T);
        while (T--)
        {
            memset(a, 0, sizeof(a));
            memset(pipei, 0, sizeof(pipei));
            res = 0;
            scanf("%d", &n);
            for (int i = 1; i <= n; i++)
                for (int j = 1; j <= n; j++)
                {
                int t;
                scanf("%d", &t);
                if (t)
                    a[i][j] = 1;
                }
            for (int i = 1; i <= n; i++)
            {
                memset(vis, 0, sizeof(vis));
                if (find(i))
                    res++;
            }
            if (res == n)
                printf("Yes
    ");
            else
                printf("No
    ");
        }
    
        return 0;
    }
     
  • 相关阅读:
    BZOJ 1101 莫比乌斯函数+分块
    BZOJ 2045 容斥原理
    BZOJ 4636 (动态开节点)线段树
    BZOJ 2005 容斥原理
    BZOJ 2190 欧拉函数
    BZOJ 2818 欧拉函数
    BZOJ 3123 主席树 启发式合并
    812. Largest Triangle Area
    805. Split Array With Same Average
    794. Valid Tic-Tac-Toe State
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7404552.html
Copyright © 2011-2022 走看看