如果把ai替换成bj,这n个向量还是线性无关即可以。
我们求一个
C∗A=B,=>C=B∗A−1
C
∗
A
=
B
,
=>
C
=
B
∗
A
−
1
矩阵求逆可以高斯消元来做,注意他原本的A矩阵也不一定就线性无关qaq
如果
Cij!=0
C
i
j
!
=
0
,说明bj可以替换ai。因此
CT
C
T
就是这张二分图的邻接矩阵。
然后我们就要求一个字典序最小的完备匹配了。
可以先随便找一个完备匹配,然后从小到大的贪心,看能否在不影响前面已确定的点的情况下找到一条交替路使得自己的标号更小。
复杂度
O(n3)
O
(
n
3
)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 310
#define mod 1000000007
inline char gc(){
static char buf[1<<16],*S,*T;
if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
return x*f;
}
int n,bf[N];
bool mp[N][N],f[N];
inline void inc(int &x,int y){x+=y;x%=mod;}
inline void dec(int &x,int y){x-=y;if(x<0) x+=mod;}
inline int ksm(int x,int k){
int res=1;for(;k;k>>=1,x=(ll)x*x%mod) if(k&1) res=(ll)res*x%mod;return res;
}
struct Matrix{
int a[N][N];
int* operator[](int x){return a[x];}
void init(bool t){
memset(a,0,sizeof(a));
if(t) for(int i=1;i<=n;++i) a[i][i]=1;
}friend Matrix operator*(Matrix a,Matrix b){
Matrix res;res.init(0);
for(int i=1;i<=n;++i)
for(int k=1;k<=n;++k)
for(int j=1;j<=n;++j)
inc(res[i][j],(ll)a[i][k]*b[k][j]%mod);return res;
}Matrix inv(){
Matrix c;c.init(1);
for(int i=1;i<=n;++i){
int r=i;while(r<=n&&!a[r][i]) ++r;
if(r!=i) for(int j=1;j<=n;++j) swap(a[r][j],a[i][j]),swap(c[r][j],c[i][j]);
int t=ksm(a[i][i],mod-2);
for(int j=1;j<=n;++j) a[i][j]=(ll)a[i][j]*t%mod,c[i][j]=(ll)c[i][j]*t%mod;
for(int j=1;j<=n;++j){
if(j==i) continue;t=a[j][i];
for(int k=1;k<=n;++k) dec(a[j][k],(ll)a[i][k]*t%mod),dec(c[j][k],(ll)c[i][k]*t%mod);
}
}return c;
}
}a,b;
inline bool find(int x){
for(int y=1;y<=n;++y){
if(!mp[x][y]||f[y]) continue;f[y]=1;
if(!bf[y]||find(bf[y])){bf[y]=x;return 1;}
}return 0;
}
inline bool find2(int x,int id){
for(int y=1;y<=n;++y){
if(!mp[x][y]||f[y]) continue;f[y]=1;
if(bf[y]==id||bf[y]>id&&find2(bf[y],id)){bf[y]=x;return 1;}
}return 0;
}
int main(){
// freopen("ferrous10.in","r",stdin);
n=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j) a[i][j]=read();
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j) b[i][j]=read();
b=b*a.inv();
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j) if(b[i][j]) mp[j][i]=1;
for(int i=1;i<=n;++i){
memset(f,0,sizeof(f));if(find(i)) continue;
puts("NIE");return 0;
}puts("TAK");
for(int i=1;i<=n;++i){
memset(f,0,sizeof(f));find2(i,i);
}for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
if(bf[j]==i) printf("%d\n",j);
return 0;
}