分析
先随便选
记\(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; }
来源:https://www.cnblogs.com/SCL123/p/12034689.html