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不为 ...
随机推荐
- Mybatis 实用篇(四)返回值类型
Mybatis 实用篇(四)返回值类型 一.返回 List.Map List<User> getUsers(); <select id="getUsers" re ...
- myeclispe2014启动后报错 Subclipse talks to Subversion via a Java API that requires access to native libraries.
解决方案: Window -> Preferences -> Team -> SVN, 将SVN接口的Client修改为如图所示
- linux计划任务(二)
计划任务的授权 1.at任务 /etc/at.allow /etc/at.deny 2.crontab任务 /etc/cron.allow /etc/cron.deny [注:如果allow文件存在, ...
- java反射简单实例
这篇博友的总结的反射知识点是比较全面的 http://www.cnblogs.com/rollenholt/archive/2011/09/02/2163758.html 下面介绍我用反射做的两个功能 ...
- 安装及运行 RabbitMQ 服务器 (linux) 失败! 安装erlang 失败,无法继续
文档 http://www.rabbitmq.com/install-rpm.html 安装前置条件 Before installing RabbitMQ, you must install Erla ...
- 布局分析002:入门级的CSS导航弹出菜单
这种弹出菜单非常有意思,也有记录的意义,甚至可以说,掌握了这种弹出菜单,基本上CSS掌握的差不多. 主要涉及下面三个重要知识: CSS的继承性质. relative absolute定位. 子选择符& ...
- Charles网络工具
Charles 是在 Mac 下常用的网络封包截取工具,在做移动开发时,我们为了调试与服务器端的网络通讯协议,常常需要截取网络封包来分析. Charles 通过将自己设置成系统的网络访问代理服务器,使 ...
- 23 DesignPatterns学习笔记:C++语言实现
DesignPatterns学习笔记:C++语言实现 (转载请注明出处:http://www.cnblogs.com/icmzn/p/5680784.html) 1. 创建型设计模式: (1)Faco ...
- Oracle EBS Export File Format
Profile Option Name Site Application Responsibility Server Server Org User Remark Export MIME type t ...
- Unity3d中使用Lua
对于手机游戏,如果可以在线更新以实现bug修复.新功能添加等等,其好处自不必多说. 通过C#的反射机制,也可以实现某种程度上的脚本级更新,具体可以参考 http://docs.unity3d.com/ ...