二分图+矩阵求逆

既然我们考虑b能替换哪些a,那么我们自然要得出b被哪些a表示,这里我们设一个矩阵C,那么C*A = B

为什么呢?直接A*C = B是不可行的,因为都是行向量,不能直接乘,那么我们转置一下,得出At*C=Bt,这样就很科学了,那么再转回来,A*Ct=B,于是Ct=B*A^-1那么矩阵求逆就能得出Ct,于是我们再转置回来就能得出B是由哪些A表示的,然后跑二分图匹配就行了。

二分图匹配理解的不是很清楚,大概是不能用之前已经用过较小的编号来更新自己,还是看CQzhangyu的吧。

矩阵求逆用取模就行了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = ;
const ll P = ;
int rd()
{
int x = , f = ; char c = getchar();
while(c < '' || c > '') { if(c == '-') f = -; c = getchar(); }
while(c >= '' && c <= '') { x = x * + c - ''; c = getchar(); }
return x * f;
}
ll power(ll x, ll t)
{
ll ret = ;
for(; t; t >>= , x = x * x % P)
if(t & )
ret = ret * x % P;
return ret;
}
void up(ll &x, const ll &t)
{
x = ((x + t) % P + P) % P;
}
int n;
int vis[N], Map[N][N], match[N];
struct Matrix {
ll a[N][N];
Matrix() { memset(a, , sizeof(a)); }
void set() { for(int i = ; i <= n; ++i) a[i][i] = ; }
Matrix friend operator * (const Matrix &a, const Matrix &b) {
Matrix ret;
for(int i = ; i <= n; ++i)
for(int k = ; k <= n; ++k) if(a.a[i][k])
for(int j = ; j <= n; ++j)
up(ret.a[i][j], a.a[i][k] * b.a[k][j] % P);
return ret;
}
Matrix Inverse()
{
Matrix c;
c.set();
for(int i = ; i <= n; ++i)
{
int now = i;
while(now <= n && !a[now][i]) ++now;
for(int j = ; j <= n; ++j)
{
swap(a[now][j], a[i][j]);
swap(c.a[now][j], c.a[i][j]);
}
ll Inv = power(a[i][i], P - );
for(int j = ; j <= n; ++j)
{
a[i][j] = a[i][j] * Inv % P;
c.a[i][j] = c.a[i][j] * Inv % P;
}
for(int k = ; k <= n; ++k) if(k != i)
{
ll t = ((P - a[k][i] % P) % P + P) % P;
for(int j = ; j <= n; ++j)
{
a[k][j] = ((a[k][j] + t * a[i][j] % P) % P + P) % P;
c.a[k][j] = ((c.a[k][j] + t * c.a[i][j] % P) % P + P) % P;
}
}
}
return c;
}
void print()
{
for(int i = ; i <= n; ++i)
{
for(int j = ; j <= n; ++j) printf("%d ", a[i][j]);
puts("");
}
}
} a, b, c, d;
bool dfs(int u)
{
for(int i = ; i <= n; ++i) if(!vis[i] && Map[u][i])
{
vis[i] = ;
if(!match[i] || dfs(match[i]))
{
match[i] = u;
return true;
}
}
return false;
}
bool dfs(int u, int lev)
{
for(int i = ; i <= n; ++i) if(!vis[i] && Map[u][i])
{
vis[i] = ;
if(match[i] == lev || (match[i] > lev && dfs(match[i], lev)))
{
match[i] = u;
return true;
}
}
return false;
}
int main()
{
// freopen("ferrous.in", "r", stdin);
// freopen("ferrous.out", "w", stdout);
n = rd();
for(int i = ; i <= n; ++i)
for(int j = ; j <= n; ++j)
a.a[i][j] = rd();
for(int i = ; i <= n; ++i)
for(int j = ; j <= n; ++j)
b.a[i][j] = rd();
c = b * a.Inverse();
for(int i = ; i <= n; ++i)
for(int j = ; j <= n; ++j) if(c.a[i][j])
Map[j][i] = ;
int ans = ;
for(int i = ; i <= n; ++i)
{
memset(vis, , sizeof(vis));
ans += dfs(i);
}
if(ans < n)
{
puts("NIE");
return ;
}
for(int i = ; i <= n; ++i)
{
memset(vis, , sizeof(vis));
dfs(i, i);
}
puts("TAK");
for(int i = ; i <= n; ++i)
for(int j = ; j <= n; ++j) if(match[j] == i)
printf("%d\n", j);
// fclose(stdin);
// fclose(stdout);
return ;
}

bzoj3168的更多相关文章

  1. 【BZOJ3168】[Heoi2013]钙铁锌硒维生素 高斯消元求矩阵的逆+匈牙利算法

    [BZOJ3168][Heoi2013]钙铁锌硒维生素 Description 银河队选手名单出来了!小林,作为特聘的营养师,将负责银河队选手参加宇宙比赛的饮食.众所周知,前往宇宙的某个星球,通常要花 ...

  2. BZOJ3168: [Heoi2013]钙铁锌硒维生素

    设$A^TC=B^T$,这样$C_{ij}$表示$B_j$的线性表出需要$A_i$,那么$B_j$可以替换$A_i$,根据$C=(A^T)^{-1}B^T$求出$C$.要求字典序最小完美匹配,先求任意 ...

  3. bzoj3168 钙铁锌硒维生素 (矩阵求逆+二分图最小字典序匹配)

    设第一套为A,第二套为B 先对于每个B[i]判断他能否替代A[j],即B[i]与其他的A线性无关 设$B[i]=\sum\limits_{k}{c[k]*A[k]}$,那么只要看c[j]是否等于零即可 ...

  4. BZOJ3168. [HEOI2013]钙铁锌硒维生素(线性代数+二分图匹配)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3168 题解 首先,我们需要求出对于任意的 \(i, j(1 \leq i, j \leq ...

随机推荐

  1. Linux上mysql修改密码

    http://www.cnblogs.com/wangjiangze/archive/2011/03/03/1970105.html   MySQL中修改密码及访问限制设置详解

  2. AVL平衡树的插入例程

    /* **AVL平衡树插入例程 **2014-5-30 11:44:50 */ avlTree insert(elementType X, avlTree T){ if(T == NULL){ T = ...

  3. POJ 1753 (枚举+DFS)

    Flip Game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 40632   Accepted: 17647 Descr ...

  4. C++ &quot;#&quot;的作用和使用方法

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/48879093 1 #和##的作用和使用 ...

  5. Spring Boot中使用RSocket

    1. 概述 RSocket应用层协议支持 Reactive Streams语义, 例如:用RSocket作为HTTP的一种替代方案.在本教程中, 我们将看到RSocket用在spring boot中, ...

  6. linux 块设备驱动(二)——块设备数据结构

    本文来源于: 1. http://www.cnblogs.com/dyllove98/archive/2013/07/01/3165567.html 块设备相关的数据结构以及接口: 块设备接口则相对复 ...

  7. poj 1730Perfect Pth Powers(分解质因数)

                                                             id=1730">Perfect Pth Powers Time Li ...

  8. ElasticSearch(十一)批量CURD bulk

    1.bulk语法 POST /_bulk { "delete": { "_index": "test_index", "_type ...

  9. Android笔记之manifestPlaceholders

    有时根据项目需要,AndroidManifest.xml中的meta-data的值分测试和正式 为了能自动地更换meta-data值,就需要用到manifestPlaceholders 语法:mani ...

  10. 【洛谷 2405】 non天平

    题目背景 non最近正在为自己的体重而苦恼,他想称量自己的体重.于是,他找来一个天平与许多砝码. 题目描述 砝码的重量均是n的幂次,n^1.n^2.n^3.n^4.n^5的……non想知道至少要多少个 ...