Problem Specification Value
Time Limit 10 Sec
Memory Limit 162 MB
Submit 3604
Solved 1729

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

HINT

Source


交换任意两列、两行不会改变最终的结果, 黑白位置对应的排布也不会变化.

所以我们可以建一个二分图, 然后把被染黑的点的横纵坐标连在一起, 二分图匹配一下就可以了.



#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>

using namespace std;
const int maxn = 210, maxm = 40010;

class Dinic
{
public:
    struct edge
    {
        int u, v;
        edge *next;
    };
    edge *edges[maxn], epool[maxm];
    int n, cnt, from[maxn], used[maxn];
    void addedge(int u, int v)
    {
        edge *p = &epool[cnt++];
        p->u = u; p->v = v;
        p->next = edges[u]; edges[u] = p;
        return ;
    }
    bool match(int p)
    {
        for (edge *ep = edges[p]; ep; ep = ep->next)
            if (!used[ep->v]) {
                used[ep->v] = true;
                if (!from[ep->v] || match(from[ep->v])) {
                    from[ep->v] = p;
                    return true;
                }
            }
        return false;
    }
    int eval(void)
    {
        memset(from, 0, sizeof(from));
        int res = 0;
        for (int i = 1; i <= n; i++) {
            memset(used, 0, sizeof(used));
            if (match(i))
                res++;
        }
        return res;
    }
    void reset(int n_)
    {
        n = n_;
        memset(edges, 0, sizeof(edges));
        cnt = 0;
        return ;
    }
} graph;

int n, T;

int main(int argc, char** argv)
{
    scanf("%d", &T);
    for (int idx = 1; idx <= T; idx++) {
        scanf("%d", &n);
        graph.reset(n);
        int tot = 0;
        for (int i = 1; i <= n; i++)
            for (int j = 1, a; j <= n; j++) {
                scanf("%d", &a);
                if (a > 0) {
                    tot++;
                    graph.addedge(i, j);
                }
            }
        int res = graph.eval();
        printf("%s\n", res >= n ? "Yes" : "No");
    }
    return 0;
}

from pydatagen import *
T = randrange(1, 10)
printf("%d\n", T)
for i in range(0, T):
    n = randrange(10, 200)
    printf("%d\n", n)
    for j in range(0, n):
        for k in range(0, n):
            if possibility(2.0 / n):
                printf("1 ")
            else:
                printf("0 ")
        printf("\n")
    pass