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 1n100

and 0kn, 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 1Sample 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 2Sample 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;
}

 

;

  

转载于:https://www.cnblogs.com/minun/p/10811652.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值