1 /*HDU1498
2 题目大意:
3 给出N*N(100以内)的矩阵,矩阵上填气球的标号(1--50),给定 K
4 问,哪些编号的气球是不能一次在K次以内拿完的。每次拿取的过程是:选择一行或者一列,再在其中选一个气球,其余的下一次不能再选。
5
6 思考:
7 变种的棋盘问题。
8 但是要枚举气球编号(分类讨论).
9 这样,就是找到最大的匹配,即最多能放置互不在同一行或一列的气球。
10 这个匹配数小于等于K,则气球能全部被拿完。
11 复杂度为:O(50*200*200)
12 */
13 #include <iostream>
14 #include <cmath>
15 #include <algorithm>
16 #include <string.h>
17 #include <stdio.h>
18 #include <set>
19 #include <stack>
20 #include <vector>
21 #define maxn 210
22 using namespace std;
23 vector<int> G[maxn];
24 int match[maxn];
25 bool visit[maxn];
26 int ans[55];
27 int mat[maxn][maxn];
28 int cnt;
29 int N,K;
30 void read(){
31 for(int i=1;i<=N;i++){
32 for(int j=1;j<=N;j++) scanf("%d",&mat[i][j]);
33 }
34 }
35 void init(int k){
36 for(int i=1;i<=2*N;i++) G[i].clear();
37 for(int i=1;i<=N;i++){
38 for(int j=1;j<=N;j++){
39 if (mat[i][j]==k){
40 int a=i,b=j+N;
41 G[a].push_back(b);
42 G[b].push_back(a);
43 }
44 }
45 }
46 }
47 bool dfs(int s)//找到从s点出发的可增广路
48 {
49 for(int i=0;i<G[s].size();i++){
50 int v=G[s][i];
51 if (!visit[v]){
52 visit[v]=true;
53 if (match[v]==0 || dfs(match[v])){//说明v对应的项有增广路
54 match[v]=s;//修改v的对应项(即互斥点)是s
55 return true;
56 }
57 }
58 }
59 return false;
60 }
61
62 int hungary(){
63 int ans=0;
64 memset(match,0,sizeof(match));//清空匹配
65 for(int i=1;i<=2*N;i++){
66 memset(visit,0,sizeof(visit));//注意清空增广路
67 if (dfs(i)) ans++;
68 }
69 return ans/2;
70 }
71 void solve(){
72 cnt=0;
73 for(int i=1;i<=50;i++){
74 init(i);
75 if (hungary()>K) ans[cnt++]=i;
76 }
77 }
78 int main(){
79 while(cin>>N>>K){
80 if (!N && !K) break;
81 read();
82 solve();
83 if (cnt==0) puts("-1");
84 else {
85 for(int i=0;i<cnt;i++)
86 if (i==cnt-1) printf("%d\n",ans[i]);else printf("%d ",ans[i]);
87 }
88 }
89 }