分析
先随便选
记(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("
");
}
else printf("\(^o^)/
");
}
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;
}