Description
   给你一个01矩阵,你每次操作可以交换两行或者交换两列。
   问你是否能得到一个矩阵使得矩阵的主对角线(左上角到右下角的连线)都为1。
Solution
   这是一道[ZJOI2007]的题。
   因为同行同列的点,变化后仍然是同行同列的。
   因为对角线都是不同行不同列的,所以我们只要找不同行同列的是否到了n个就可以了。
   如果原矩阵中第i行第j列为1,那么就Xi -> Yj连一条边。然后跑最大匹配即可。
Notice
因为有多组数据,千万要记得每次对match数组清零。
Code
匈牙利算法版本:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
using namespace std;
const ll INF = 1e9, Mo = 998244353;
const int N = 200;
const double eps = 1e-6;
namespace slow_IO
{
    ll read()
    {
        ll x = 0; int zf = 1; char ch = getchar();
        while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
        if (ch == '-') zf = -1, ch = getchar();
        while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
        return x * zf;
    }
    void write(ll y)
    {
        if (y < 0) putchar('-'), y = -y;
        if (y > 9) write(y / 10);
        putchar(y % 10 + '0');
    }
}
using namespace slow_IO;
int head[N + 5], vis[N + 5], match[N + 5];
int edgenum = 0;
struct node
{
    int vet, next;
}edge[N * N + 5];
void addedge(int u, int v)
{
    edge[edgenum].vet = v;
    edge[edgenum].next = head[u];
    head[u] = edgenum++;
}
int Find(int u)
{
    travel(i, u)
    {
        int v = edge[i].vet;
        if (vis[v]) continue;
        vis[v] = 1;
        if (!match[v] || Find(match[v]))
        {
            match[v] = u;
            return 1;
        }
    }
    return 0;
}
int sqz()
{
    int H_H = read();
    while (H_H--)
    {
        int n = read();
        int ans = 0; edgenum = 0;
        rep(i, 1, n) head[i] = -1, match[i] = 0;
        rep(i, 1, n)
            rep(j, 1, n)
            {
                int x = read();
                if (x) addedge(i, j);
            }
        rep(i, 1, n)
        {
            rep(j, 1, n) vis[j] = 0;
            if (Find(i)) ans++;
        }
        if (ans == n) puts("Yes");
        else puts("No");
    }
    return 0;
}
Hopcroft-Karp算法版本:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
using namespace std;
const ll INF = 1e9, Mo = 998244353;
const int N = 200;
const double eps = 1e-6;
namespace slow_IO
{
    ll read()
    {
        ll x = 0; int zf = 1; char ch = getchar();
        while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
        if (ch == '-') zf = -1, ch = getchar();
        while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
        return x * zf;
    }
    void write(ll y)
    {
        if (y < 0) putchar('-'), y = -y;
        if (y > 9) write(y / 10);
        putchar(y % 10 + '0');
    }
}
using namespace slow_IO;
int head[N + 5], vis[N + 5], Matchx[N + 5], Matchy[N + 5], Disx[N + 5], Disy[N + 5];
int edgenum = 0, n, Dis;
struct node
{
    int vet, next;
}edge[N * N + 5];
void addedge(int u, int v)
{
    edge[edgenum].vet = v;
    edge[edgenum].next = head[u];
    head[u] = edgenum++;
}
queue<int> Q;
int bfs()
{
    rep(i, 1, n)
    {
        Disx[i] = Disy[i] = -1;
        if (!Matchx[i]) Q.push(i), Disx[i] = 0;
    }
    Dis = INF;
    while (!Q.empty())
    {
        int u = Q.front(); Q.pop();
        if (Disx[u] > Dis) continue;
        travel(i, u)
        {
            int v = edge[i].vet;
            if (~Disy[v]) continue;
            Disy[v] = Disx[u] + 1;
            if (!Matchy[v]) Dis = Disy[v];
            else
            {
                Disx[Matchy[v]] = Disy[v] + 1;
                Q.push(Matchy[v]);
            }
        }
    }
    return Dis != INF;
}
int dfs(int u)
{
    travel(i, u)
    {
        int v = edge[i].vet;
        if (!vis[v] && Disy[v] == Disx[u] + 1)
        {
            vis[v] = 1;
            if (!Matchy[v] || dfs(Matchy[v]))
            {
                Matchy[v] = u, Matchx[u] = v;
                return 1;
            }
        }
    }
    return 0;
}
int MaxMatch()
{
    int Match = 0;
    while (bfs())
    {
        rep(i, 1, n) vis[i] = 0;
        rep(i, 1, n) if (!Matchx[i]) Match += dfs(i);
    }
    return Match;
}
int sqz()
{
    int H_H = read();
    while (H_H--)
    {
        n = read();
        int ans = 0; edgenum = 0;
        rep(i, 1, n) head[i] = -1, Matchx[i] = Matchy[i] = 0;
        rep(i, 1, n)
            rep(j, 1, n)
            {
                int x = read();
                if (x) addedge(i, j);
            }
        if (MaxMatch() == n) puts("Yes");
        else puts("No");
    }
    return 0;
}