https://vjudge.net/problem/Kattis-latinsquare
这题在说白了就是一道数独,hhhhhhhhh
训练赛的时候根本看不出是一道二分图,甚至根本没往这方面想,结束时看题解也是莫名奇妙(那篇题解没有讲解),到后面问了学长,学长提了一嘴。瞬间顿悟!!!!
首先,这个是一个二分图覆盖的模型每一行每一列只能有一个同一数字。
于是乎我们将他分解成多步,每一步就是将一个种类的数字,填进矩阵。
所以,每一步就是一个最小点覆盖,将第i行和第j列抽象成两个点,i -> j就是一条边,找不同i且不同j进行一个匹配,将所有的i和j匹配完后,就是一个最小点覆盖。
(我自己的理解,讲的不清楚可以看看代码,代码比较好理解)
#include <bits/stdc++.h> using namespace std; int maps[110][110]; int bj[110], match[110]; bool mark[110]; int n, k; int find(int x); int main() { scanf("%d%d", &n, &k); for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) { int x; scanf("%d", &x); maps[i][j] = x; mark[x] = 1; } for (int i = 1; i <= n; i++) { if (mark[i]) continue; memset(match, 0, sizeof match); for (int j = 1; j <= n; j++) { memset(bj, 0, sizeof bj); find(j); } for (int j = 1; j <= n; j++) { maps[match[j]][j] = i; } } cout << "YES\n"; for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) cout << maps[i][j] << " "; cout << endl; } return 0; } int find(int x) { for (int i = 1; i <= n; i++) { if (!bj[i] && !maps[x][i]) { bj[i] = 1; if (!match[i] || find(match[i])) { match[i] = x; return 1; } } } return 0; }