Kattis - superdoku (二分图匹配)- 2018 ICPC North American Qualifier Contest
Alice and Bob are big fans of math. In particular, they are very excited about playing games that are related to numbers. Whenever they see a puzzle like Sudoku, they cannot stop themselves from solving it. The objective of Sudoku is to fill a 9×9 grid with digits so that each column, each row, and each of the nine subgrids that compose the grid (also called “boxes”, “blocks”, or “regions”) contains all of the digits from 1 to 9
. The puzzle setter provides a partially completed grid, which for a well-posed puzzle has a single solution.
After many years of solving Sudoku problems, Alice and Bob are tired of Sudoku. They have been trying to develop a harder variation of Sudoku, which they are calling Superdoku. In Superdoku, the grid is bigger – n×n
instead of just 9×9. However, the “block” constraints are impossible to formulate when there are no further constraints on n. Therefore, there are no block constraints in Superdoku. Instead, the goal is simply to make sure that each column and each row in the grid contains all of the integers from 1 to n. After playing for a while in the standard way (where any of the grid cells may have previously been filled in), they decide that the game is too difficult and they want to simplify it. Therefore, they decide to make the initial grid further constrained. They constrain the board by filling in the first k
rows completely.
Alice and Bob both believe that Superdoku is solvable. However, since n
could be very big, it may still take a long time to figure out a solution. They don’t want to spend too much time on this single game, so they are asking for your help!
Input
The input consists of a single test case. The first line lists two space-separated integers 1≤n≤100
and 0≤k, denoting the size of the grid (n×n) and the number of rows k that are already filled in. Each of the following k lines contains n space-separated integers, denoting the first k given rows. All integers in these k lines are between 1 and n
.
Output
Output either “yes” or “no” on the first line, indicating if there is a solution. If there is no solution, do not output anything more. If there is a solution, output n
more lines, each containing n
space-separated integers, representing a solution. If there are multiple solutions, output any one of them.
Sample Input 1 Sample Output 1 4 2 1 2 3 4 2 3 4 1 yes 1 2 3 4 2 3 4 1 3 4 1 2 4 1 2 3
Sample Input 2 Sample Output 2 4 2 1 2 3 4 2 2 2 2 no
题目大意:
一个n*n的图给你前k行卫问是否可以补充完整使每一行每一列都是1-n n个数字;
题解思路:
对于一个矩阵来说如果题目给的前k行是合法的,那么一定有可行的解是整个矩阵合法;
所以我们只要保证填入的每一行都是合法的那么到最后的矩阵一定是合法的;
二分图匹配每点,保证每一行对之前的矩阵来说是合法即可;
如果填入x本行之前出现过,对之前的x所在的位置行进调整
#include<bits/stdc++.h> using namespace std; #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) const int maxn=105; int nmap[maxn][maxn],visc[maxn][maxn],visr[maxn][maxn],pos[maxn][maxn],vis[105]; int n,k; int dfs(int x,int y)//二分图匹配每一行 { for(int i=1;i<=n;i++) { if(!visc[y][i]&&!vis[i])//如果当前列没有出现过且没有标记 { vis[i]=1;//标记 if(!visr[x][i]||dfs(x,pos[x][i]))//如果当前行未出现过 或可以进行前面的调整使其合法 { nmap[x][y]=i;//图 pos[x][i]=y;//记录出现的位置 visr[x][i]=1;//行的标记 return 1; } } } return 0; } int main() { scanf("%d%d",&n,&k); for(int i=1;i<=k;i++) for(int j=1;j<=n;j++) { scanf("%d",&nmap[i][j]); if(visr[i][nmap[i][j]]||visc[j][nmap[i][j]]) goto f; visr[i][nmap[i][j]]=1; visc[j][nmap[i][j]]=1; }//判断图是否合法 //cout<<"here"<<endl; for(int i=k+1;i<=n;i++) { for(int j=1;j<=n;j++) { //cout<<i<<" "<<j<<endl; mem(vis,0); dfs(i,j); } for(int j=1;j<=n;j++)//更新列标记 visc[j][nmap[i][j]] = 1; } puts("yes"); for(int i=1;i<=n;i++) { for(int j=1;j<n;j++) printf("%d ",nmap[i][j]); printf("%d\n",nmap[i][n]); } return 0; f:; puts("no");;; return 0; }
;