Superdoku

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 9 \times 9 9×9 grid with digits so that each column, each row, and each of the nine ( 3 × 3 ) (3 \times 3) (3×3) subgrids that compose the grid (also called “boxes”, “blocks”, or “regions”) contains all of the digits from 11 to 99. 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 n \times n n×n instead of just 9 × 9 9 \times 9 9×9. However, the “block” constraints are impossible to formulate when there are no further constraints on nn. 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 11 to nn. 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 kk rows completely.

Alice and Bob both believe that Superdoku is solvable. However, since nn 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 1 \le n \le 100 1n100 and 0 k n 0 \le k \le n 0kn, denoting the size of the grid ( n × n ) (n \times n) (n×n) and the number of rows k that are already filled in. Each of the following k lines contains nn space-separated integers, denoting the first kk given rows. Allintegers in these k lines are between 11 and nn.

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 nn more lines, each containing nn space-separated integers, representing a solution. If there are multiple solutions, output any one of them.

本题答案不唯一,符合要求的答案均正确

样例输入
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
样例输入
4 2
1 2 3 4
2 2 2 2
样例输出
no

将n*n的网格填满,每行每列必须出现1-n中的所有数。
这本来是一道搜索题,可n是100,搜索的时间复杂度是O(n!),不敢想象。
很显然,如果输入的k行符合条件,那么必然是有解的,用每行的轮换式去套也是能套出答案的。
如果前看行符合,那么,e[i][j]表示第i列可以填j这个数字,如果第i列填了j这个数字,其余列就不能填j了。
对于k+1之后每一行,可以跑一遍二分图匹配,当然这n-k列都是完美媲美匹配。
时间:搜索只能过一半的点,二分图50ms,差太多了吧。。。

#include<bits/stdc++.h>
using namespace std;
#define Init(arr,val) memset(arr,val,sizeof(arr))
const int inf=0x3f3f3f3f,mod=1e9+7,MAXN=101;
typedef long long ll;
bool r[MAXN][MAXN],l[MAXN][MAXN];//搜索里的判断第i行、列j这个数字有没有出现过,可以用e[][]代替,懒得改了。。
bool e[MAXN][MAXN];//e[i][j]第i列能填j
int pre[MAXN],ans[MAXN][MAXN];//数字j被pre[j] 这列填了。
bool vis[MAXN];
int n,k,x;
bool dfs(int i){
    for(int j=1;j<=n;++j){
        if(!e[i][j]||vis[j])continue;
        vis[j]=1;
        if(!pre[j]||dfs(pre[j])){
            pre[j]=i;
            return 1;
        }
    }
    return 0;
}
void solve(int row){//第row行跑一下匹配
    Init(pre,0);
    for(int i=1;i<=n;++i){
        Init(vis,0);
        dfs(i);
    }
    for(int i=1;i<=n;++i){
        ans[row][pre[i]]=i;
        e[pre[i]][i]=0;
    }
}
int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    std::cout.tie(0);
    Init(e,1);
    cin>>n>>k;
    for(int i=1;i<=k;++i){
        for(int j=1;j<=n;++j){
            cin>>x;
            if(r[i][x]||l[j][x]){
                cout<<"no";
                return 0;
            }
            r[i][x]=l[j][x]=1;
            e[j][x]=0;
            ans[i][j]=x;
        }
    }
    cout<<"yes\n";
    for(int i=k+1;i<=n;++i)solve(i);
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j){
            cout<<ans[i][j]<<" ";
        }
        cout<<endl;
    }
    return 0;
}