BZOJ3168. [HEOI2013]钙铁锌硒维生素(线性代数+二分图匹配)
题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=3168
题解
首先,我们需要求出对于任意的 \(i, j(1 \leq i, j \leq n)\),第二套中的第 \(j\) 个机器人是否可以替换第一套中的第 \(i\) 个机器人。
将第 \(i\) 个机器人提供的第 \(j\) 种营养的量记为 \(a_{i, j}\),我们可以得到一个 \(n \times n\) 的矩阵 \(A\)。那么,整套机器人能搭配出任何营养需求等价于将矩阵 \(A\) 化为行阶梯形矩阵后拥有 \(n\) 个非零行,即该矩阵为满秩矩阵。
由于满秩矩阵即可逆矩阵,矩阵 \(A\) 可逆等价于矩阵 \(A\) 的行列式值 \(|A| \neq 0\),因此,我们的任务是快速求出矩阵 \(A\) 在替换了某一行的元素后的行列式的值。不难想到通过行列式按行展开法则来计算行列式的值,即假如替换的是矩阵 \(A\) 的第 \(i\) 行,那么有(以下用 \(A_{i, j}\) 表示矩阵的 \((i, j)\) 元的代数余子式,矩阵的行列标号为 \(1 \sim n\)):
\]
其中的 \(a_{i, k}(1 \leq k \leq n)\) 为第 \(i\) 行替换后的元素值。由于代数余子式 \(A_{i, k}\) 的值与第 \(i\) 行本身的元素无关,因此我们可以先用 \(O(n^3)\) 的时间求出矩阵 \(A\) 的伴随矩阵,从而得到矩阵所有元素对应的代数余子式的值。具体地,设矩阵 \(A\) 的伴随矩阵为 \(A^*\),根据 \(A^{-1} = \frac{1}{|A|}A^*\) 可得 \(A^* = |A|A^{-1}\),由于可以在 \(O(n^3)\) 的时间内求出矩阵 \(A\) 的逆矩阵 \(A^{-1}\)(并顺便求出矩阵 \(A\) 的行列式值 \(|A|\)),因此自然能够在相同的时间内求出伴随矩阵。得到所有元素的代数余子式的值后,我们便能在 \(O(n)\) 的时间内求出单次行替换后矩阵的行列式值。一共需要进行 \(O(n^2)\) 次替换与判断,故预处理出每个机器人对应的替换集合所需的总时间复杂度为 \(O(n^3)\)。
预处理完毕后,我们就可以通过求二分图匹配来寻找解的方案。不过,注意到题目要求求出字典序最小的匹配,因此直接通过一次二分图匹配得到的方案并不是我们所需要的答案,我们需要在此基础上再进行一次贪心。具体地,我们从小到大枚举编号 \(i\),然后判断在第一套机器人中编号小于 \(i\) 的机器人的匹配状态不变的情况下,编号为 \(i\) 的机器人能否与编号更优的机器人匹配即可。
总时间复杂度为 \(O(n^3)\)。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 3e2 + 10, mod = 1e9 + 7;
void add(int& x, int y) {
x += y;
if (x >= mod) {
x -= mod;
}
}
int mul(int x, int y) {
return (long long) x * y % mod;
}
int qpow(int v, int p) {
int result = 1;
for (; p; p >>= 1, v = mul(v, v)) {
if (p & 1) {
result = mul(result, v);
}
}
return result;
}
int n, a[N][N], b[N][N], inv[N][N], adj[N][N], choice[N], visit[N], tt, answer[N];
vector<int> go[N];
void transform1(int a[N][N], int i, int j) {
for (int p = 0; p < n; ++p) {
swap(a[i][p], a[j][p]);
}
}
void transform2(int a[N][N], int i, int k) {
for (int p = 0; p < n; ++p) {
a[i][p] = mul(a[i][p], k);
}
}
void transform3(int a[N][N], int i, int j, int k) {
for (int p = 0; p < n; ++p) {
add(a[i][p], mul(a[j][p], k));
}
}
void get_adj() {
int det = 1;
for (int i = 0; i < n; ++i) {
inv[i][i] = 1;
}
for (int i = 0; i < n; ++i) {
if (!a[i][i]) {
int p = i;
for (int j = i + 1; j < n; ++j) {
if (a[j][i]) {
p = j;
}
}
if (p == i) {
puts("NIE");
exit(0);
}
transform1(a, i, p);
transform1(inv, i, p);
det = (mod - det) % mod;
}
det = mul(det, a[i][i]);
int x = qpow(a[i][i], mod - 2);
transform2(a, i, x);
transform2(inv, i, x);
for (int j = i + 1; j < n; ++j) {
int p = a[j][i];
transform3(a, j, i, (mod - p) % mod);
transform3(inv, j, i, (mod - p) % mod);
}
}
for (int i = n - 1; ~i; --i) {
for (int j = i + 1; j < n; ++j) {
int p = a[i][j];
transform3(a, i, j, (mod - p) % mod);
transform3(inv, i, j, (mod - p) % mod);
}
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
adj[i][j] = mul(inv[j][i], det);
}
}
}
bool find(int u) {
for (int i = 0; i < go[u].size(); ++i) {
int v = go[u][i];
if (visit[v] != tt) {
visit[v] = tt;
if (!~choice[v] || find(choice[v])) {
choice[v] = u;
return true;
}
}
}
return false;
}
bool find_better(int u, int down) {
for (int i = 0; i < go[u].size(); ++i) {
int v = go[u][i];
if (visit[v] != tt) {
visit[v] = tt;
if (choice[v] == down || (choice[v] > down && find_better(choice[v], down))) {
answer[u] = v;
choice[v] = u;
return true;
}
}
}
return false;
}
int main() {
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
scanf("%d", &a[i][j]);
}
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
scanf("%d", &b[i][j]);
}
}
get_adj();
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
int det = 0;
for (int k = 0; k < n; ++k) {
add(det, mul(b[j][k], adj[i][k]));
}
if (det) {
go[i].push_back(j);
}
}
}
memset(choice, -1, sizeof choice);
int total = 0;
for (int i = 0; i < n; ++i) {
++tt;
total += find(i);
}
if (total != n) {
puts("NIE");
} else {
puts("TAK");
for (int i = 0; i < n; ++i) {
++tt;
find_better(i, i);
printf("%d\n", answer[i] + 1);
}
}
return 0;
}
BZOJ3168. [HEOI2013]钙铁锌硒维生素(线性代数+二分图匹配)的更多相关文章
- BZOJ3168: [Heoi2013]钙铁锌硒维生素
设$A^TC=B^T$,这样$C_{ij}$表示$B_j$的线性表出需要$A_i$,那么$B_j$可以替换$A_i$,根据$C=(A^T)^{-1}B^T$求出$C$.要求字典序最小完美匹配,先求任意 ...
- 【BZOJ3168】[Heoi2013]钙铁锌硒维生素 高斯消元求矩阵的逆+匈牙利算法
[BZOJ3168][Heoi2013]钙铁锌硒维生素 Description 银河队选手名单出来了!小林,作为特聘的营养师,将负责银河队选手参加宇宙比赛的饮食.众所周知,前往宇宙的某个星球,通常要花 ...
- BZOJ 3168: [Heoi2013]钙铁锌硒维生素 [线性基 Hungary 矩阵求逆]
3168: [Heoi2013]钙铁锌硒维生素 题意:给一个线性无关组A,再给一个B,要为A中每个向量在B中选一个可以代替的向量,替换后仍然线性无关.判断可行和求字典序最小的解 PoPoQQQ orz ...
- 洛谷 P4100 [HEOI2013]钙铁锌硒维生素 解题报告
P4100 [HEOI2013]钙铁锌硒维生素 题目描述 银河队选手名单出来了!小林,作为特聘的营养师,将负责银河队选手参加 宇宙比赛的饮食. 众所周知,前往宇宙的某个星球,通常要花费好长好长的时间, ...
- 【BZOJ】3168: [Heoi2013]钙铁锌硒维生素
题解 Ca Fe Zn Se 显然我们既然初始矩阵就能通过线性变换变成单位矩阵,则该矩阵一定有逆 没有逆输出NIE 而且因为这些向量两两正交,则表示一个向量的时候表示方法唯一 那么我们求一个逆可以求出 ...
- BZOJ 3168 Luogu P4100 [HEOI2013]钙铁锌硒维生素 (矩阵求逆、二分图匹配)
线性代数+图论好题. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3168 (luogu) https://www.lu ...
- bzoj3168 钙铁锌硒维生素 (矩阵求逆+二分图最小字典序匹配)
设第一套为A,第二套为B 先对于每个B[i]判断他能否替代A[j],即B[i]与其他的A线性无关 设$B[i]=\sum\limits_{k}{c[k]*A[k]}$,那么只要看c[j]是否等于零即可 ...
- BZOJ 3168 Heoi2013 钙铁锌硒维生素 矩阵求逆+匈牙利算法
题目大意:给定一个n∗n的满秩矩阵A和一个n∗n的矩阵B.求一个字典序最小的1...n的排列a满足将随意一个Ai换成Bai后矩阵A仍然满秩 我们考虑建立一个二分图.假设Ai能换成Bj.就在i−> ...
- BZOJ 3168 [Heoi2013]钙铁锌硒维生素 ——矩阵乘法 矩阵求逆
考虑向量ai能否换成向量bj 首先ai都是线性无关的,然后可以a线性表出bj c1*a1+c2*a2+...=bj 然后移项,得 c1/ci*a1+...-1/ci*bj+...=ai 所以当ci不为 ...
随机推荐
- scrollView不能进行滚动
原因:scrollView里只能包含一个layout,多个时,是不能进行滚动的.
- app开发中如何利用sessionId来实现服务端与客户端保持回话
app开发中如何利用sessionId来实现服务端与客户端保持回话 这个问题太过于常见,也过于简单,以至于大部分开发者根本没有关注过这个问题,我根据和我沟通的开发者中,总结出来常用的方法有以下几种: ...
- XtrasReport 标签打印
var lblList = new List<product_LblPrt_tmp>(); using (JL_MFGEntities ctx = new JL_MFGEntities() ...
- Ural 1519 Formula 1 (DP)
题意:给定一个 n * m 的矩阵,问你能花出多少条回路. #pragma comment(linker, "/STACK:1024000000,1024000000") #inc ...
- CSS—— em的详解
字体大小在浏览器的默认样式表中有规定.一般采用em为单位,也就是相对单位,1em=16像素. 同时,像P h1等等标签都采用浏览器默认的em单位,P为1em,h1为2em等等. 两条重要的规则: 1. ...
- Anti-Anti dylib(反 反-dylib钩子(Anti-tweak))
版主提供了 anti dylib 的文章,http://bbs.chinapyg.com/thread-76158-1-1.html原理很简单,看下面源代码即可~ 在Build Settings中找 ...
- Lucene之模糊、精确、匹配、范围、多条件查询
Lucene的查询方式很 丰富,对于数值类型的数据,采取TermRangeQuery的方式,对于String类型的,就可以采取TermQuery等,查询方式了,可以通过采取合适的查询方式,检索到数据. ...
- 如何将本地数据库迁移至SQL Azure
Windows Azure的SQL Azure和SQL Server 拥有不同的体系结构,可以说是两个不同的产品.SQL Azure不完全支持或者尚不支持SQL Server的某些功能,这使得我们不能 ...
- Tempdb--查看TempDB上是否需要增加文件
SELECT [owt].[session_id], [owt].[exec_context_id], [owt].[wait_duration_ms], [owt].[wait_type], [ow ...
- WinRT支持GB2312
在SL年代,有第三方类库支持 http://encoding4silverlight.codeplex.com 在RT版本有点不兼容,一直没时间看.今天闲的卵疼,就来一段代码兼容一下RT版本,迟点整合 ...