Latin Square(二分图匹配)
作者:互联网
题目链接:https://vjudge.net/problem/Kattis-latinsquare https://open.kattis.com/problems/latinsquare
题意:用 1 - n 范围内的数填充一个 n * n 的矩阵,每一行每一列 1 - n 只能且必须出现一次,输入会预先填好 k 种数,每种数 n 个。
Input
第一行输入 n 和 k,1 ≤ n ≤ 100, 0 ≤ k ≤ n,然后输入一个 n * n 的矩阵,0表示需要填,输入保证合法。
Output
如果有合法方案,第一行输出 "YES" ,然后输出合法的矩阵,否则输出 "NO"。
Sample Input
3 1
2 0 0
0 2 0
0 0 2
Sample Output
YES
2 1 3
3 2 1
1 3 2
思路:目前遇到过的类似数独的这种题就两种做法,数据范围很小可以直接暴力,稍微大一点就是匹配问题。
对于这个题,我们考虑一个数一个数地填,也就是说考虑这个数在每一行的哪一列,那么问题就变成了二分图匹配问题,填当前这个数的时候,行与列进行二分图匹配。这样匹配出来一定是合法的,不存在"NO"的情况,因为每次都是在合法的情况下去填当前这个数,匹配过程和结果也一定合法。
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<map> #include<set> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int N = 110; int n, k; int a[N][N]; int use[N]; int vis[N], ans[N]; bool dfs(int now) { for(int i = 1; i <= n; i++) { if(a[now][i] == 0 && !use[i]) { use[i] = 1; if(!ans[i] || dfs(ans[i])) { ans[i] = now; return true; } } } return false; } int main() { scanf("%d %d", &n, &k); for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { scanf("%d", &a[i][j]); vis[a[i][j]] = 1; } } for(int i = 1; i <= n; i++) { if(vis[i]) continue; memset(ans, 0, sizeof(ans)); for(int j = 1; j <= n; j++) { memset(use, 0, sizeof(use)); dfs(j); } for(int j = 1; j <= n; j++) { a[ans[j]][j] = i; } } printf("YES\n"); for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { if(j == n) { printf("%d\n", a[i][j]); } else { printf("%d ", a[i][j]); } } } return 0; }View Code
标签:二分,Latin,匹配,int,合法,Square,include,输入 来源: https://www.cnblogs.com/lsl127/p/12939370.html