题目链接uoj
题面
前置知识:稳定婚姻问题模型的应用
看完题面后,很容易想到
1.对于每一行,希望选的数字尽量靠前。重置尽可能多的数字;
2.对于每一个数字x,希望在所选行的位置尽量靠后。尽量避免和其他行的x冲突;
再结合题面对A的描述,我们可以知道
1.对于第i行,所有数字有不同的匹配优先级
2.对于数字x,所有行有不同的匹配优先级
数字和行,一对一匹配。恰好就是典型的稳定婚姻问题模型
现在我们构造一下非法样例验证一下我们的想法。
i x x(y)x x x x x x x x
j x y y y y
明显的在以上样例中,对于第j行的x优先级更高,对于x第j行的优先级更高。
根据稳定婚姻问题模型的描述,我们应该把x和j匹配才是更优的(YY一下我们会发现这样匹配的确是更优的
时间复杂度:O(nm)
#include<bits/stdc++.h>
using namespace std;
const int maxn = 205;
const int maxm = 405;
namespace Input{
const int BUF = 65536;
char buf[BUF + 1];
char *head = buf, *tail = buf;
}
inline char inputchar(){
using namespace Input;
if(head == tail)*(tail = (head = buf) + fread(buf, 1, BUF, stdin)) = 0;
return *head++;
}
inline void io(int &ret){
char ch = inputchar();
while(ch < '0' || ch > '9')ch = inputchar();
ret = ch - '0';
ch = inputchar();
while(ch >= '0' && ch <= '9'){
ret = ret * 10 + ch - '0';
ch = inputchar();
}
}
int n,m;
int M[maxn][maxn],Wam[maxn][maxn],tmp[maxn],vis[maxn];
queue<int>Q;
inline void init(){
io(n),io(m);
int x;
memset(tmp,0,(n+1)*sizeof(int));
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
io(x);
if(x){
M[i][++tmp[i]]=x;
Wam[x][i]=j;
}
}
}
}
inline void sol(){
for(int i=1;i<=n;++i){
Q.push(i);
tmp[i]=1;
}
int u,v;
memset(vis,0,(n+1)*sizeof(int));
while(Q.size()){
u=Q.front();Q.pop();
v=M[u][tmp[u]];
if(vis[v]&&Wam[v][u]<Wam[v][vis[v]]){
++tmp[u];
Q.push(u);
}else{
if(vis[v])Q.push(vis[v]);
vis[v]=u;
}
}
for(int i=1;i<=n;++i){
printf("%d%c",M[i][tmp[i]],i==n?'\n':' ');
}
}
int main(){
//freopen("123.in","r",stdin);
int t;
io(t);
while(t--){
init();
sol();
}
}