每次选一个未放入答案排列的数字x,选还没被覆盖的最右的出现位置覆盖,如果这导致原先一个已决策的数字决策失效(即这一行已经覆盖过)则重新决策这个数字,递归进行至不冲突为止,由于增广路的长度为O(n),总时间复杂度不超过读入复杂度。
#include<bits/stdc++.h> char ib[20000007],*ip=ib; int _(){ int x=0; while(*ip<48)++ip; while(*ip>47)x=x*10+*ip++-48; return x; } int T,n,m,v[207][407],as[207],del[207],pp[207],ps[207][207]; struct pos{ int x,y; }; void find(int); void set(int x,int y,int c){ del[x]=y; int z=as[x]; as[x]=c; if(z)find(z); } void find(int x){ while(1){ int v=ps[x][pp[x]]; if((v&65535)<del[v>>16])return set(v>>16,v&65535,x); --pp[x]; } } int main(){ fread(ib,1,sizeof(ib),stdin); for(T=_();T;--T){ n=_(),m=_(); for(int i=1;i<=n;++i){ pp[i]=as[i]=0; del[i]=m+1; for(int j=1;j<=m;++j)v[i][j]=_(); } for(int j=1;j<=m;++j){ for(int i=1;i<=n;++i)if(v[i][j]){ int x=v[i][j]; ps[x][++pp[x]]=i<<16|j; } } for(int i=1;i<=n;++i)find(i); for(int i=1;i<=n;++i)printf("%d ",as[i]);puts(""); } return 0; }