分析
先随便选
记\(p[i][j]\)表示\(j\)这个数在第\(i\)行的位置,考虑不合法的情况:
假设第i行选择的数为\(x\),第\(j\)行选择的为\(y\),且\(p[i][x]<p[j][x]<p[j][y]\),那么在第\(p[j][x]\)列就会有两个\(x\)出现,不满足条件。
那么,我们最终的目标就是使得上述情况不存在
可以转化成稳定婚姻问题:
- 对于每一行,优先去选在左边的
- 对于每一个数,优先匹配\(p[i][x]\)大的\(i\)
代码
#include<bits/stdc++.h>
#define rep(X,A,B) for(int X=A;X<=B;X++)
#define tep(X,A,B) for(int X=A;X>=B;X--)
#define LL long long
const int N=210;
using namespace std;
int n,m,chk;
int ans[N],vis[N],p[N][N],a[N][N];
queue<int>Q;
void READ(){
scanf("%d%d",&n,&m);
int x=0;
rep(i,1,n){
rep(j,1,m){
scanf("%d",&x);
if(x)p[i][x]=j;
a[i][j]=x;
}
}
}
void SOLVE(){
rep(i,1,n)ans[i]=vis[i]=0,Q.push(i);
while(!Q.empty()){
int x=Q.front();Q.pop();
rep(o,1,m){
int i=a[x][o];
if(!i)continue;
if(!vis[i]||(vis[i]&&p[x][i]>p[vis[i]][i])){
if(vis[i]){
Q.push(vis[i]);
ans[vis[i]]=0;
}
vis[i]=x;
ans[x]=i;
break;
}
}
}
int now=1;
rep(i,1,n)if(!ans[i])now=0;
if(now){
rep(i,1,n)printf("%d ",ans[i]);
printf("\n");
}
else printf("\\(^o^)/\n");
}
int CHK(){
rep(i,1,n){
if(!ans[i])return 0;
int now=0;
rep(j,1,m){
if(a[i][j]==ans[i])now=a[i][j];
if(now)a[i][j]=now;
}
}
rep(j,1,m){
rep(i,1,n)vis[i]=0;
rep(i,1,n)vis[a[i][j]]++;
rep(i,1,n)if(vis[i]>1)return 0;
}
return 1;
}
void SSOLVE(){
READ();
SOLVE();
}
int main(){
int T;
scanf("%d",&T);
while(T--)SSOLVE();
return 0;
}