【BZOJ】3168: [Heoi2013]钙铁锌硒维生素
题解
显然我们既然初始矩阵就能通过线性变换变成单位矩阵,则该矩阵一定有逆
没有逆输出NIE
而且因为这些向量两两正交,则表示一个向量的时候表示方法唯一
那么我们求一个逆可以求出这个矩阵消成单位矩阵的线性表示,再拿第二个矩阵和逆矩阵相乘可以得到第二个矩阵每个行向量用第一个矩阵的行向量唯一的表示方法
如果第二套的第k个行向量的表示里第一行h个行向量系数不为0,则h可以被k替代
建图二分图匹配,先求一个匹配出来,然后对于每个点从前往后固定匹配看看能不能使得靠前的更小
说的很高端吧
算了我简单一点说
就是一考虑初始的矩阵,什么两三行加加减减乘个系数,是可以消成单位1的,这个可以用类似高斯消元的方法解决,实际上如果你了解矩阵求逆的话你就知道我在给这个矩阵求逆矩阵
如果消不成就是NIE了
如果你不了解的话,你可以把每次变换每个行所用到的系数记下来,变成另一个矩阵\(B\)
那么我们考虑第二套的某个向量,
\((b_{1},b_{2}...b_{n}) = \sum_{i = 1}^{n} c_{i} (a_{1},a_{2}..a_{n})\)
显然如果\(c_{i}\)有数的话,我门可以把\(c_{i}\)移到等号左边,把第二套的这个向量移到等式右边,就证明\(i\)可以被这个向量换掉了
这个系数可以用两个矩阵相乘求出来
图建出来了,那就是跑二分图了
我们先求出一个完备匹配来,没有就是NIE,有的话对于\(1-n\)从小到大枚举能更新的匹配点,然后把这个点强制不选再跑二分图看看会不会合法
代码
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 305
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {x = -x;putchar('-');}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
int N;
int g[305][305],matc[305],matk[305];
bool vis[305];
bool flag = 0;
struct Matrix {
db f[305][305];
Matrix() {memset(f,0,sizeof(f));}
void unit() {
for(int i = 1 ; i <= N ; ++i) {
f[i][i] = 1.0;
}
}
friend Matrix operator * (const Matrix &a,const Matrix &b) {
Matrix c;
for(int i = 1 ; i <= N ; ++i) {
for(int j = 1 ; j <= N ; ++j) {
for(int k = 1 ; k <= N ; ++k) {
c.f[i][j] += a.f[i][k] * b.f[k][j];
}
}
}
return c;
}
friend Matrix operator ~(Matrix a) {
Matrix b;
b.unit();
for(int i = 1 ; i <= N ; ++i) {
int l = i;
for(int j = i + 1; j <= N ; ++j) {
if(fabs(a.f[j][i]) > fabs(a.f[l][i])) l = j;
}
if(fabs(a.f[l][i]) < 1e-8) {flag = 1;return b;}
if(i != l) {
for(int j = 1 ; j <= N ; ++j) {
swap(a.f[i][j],a.f[l][j]);
swap(b.f[i][j],b.f[l][j]);
}
}
db t = 1.0 / a.f[i][i];
for(int j = 1 ; j <= N ; ++j) {
a.f[i][j] *= t;
b.f[i][j] *= t;
}
for(int j = 1 ; j <= N ; ++j) {
if(i == j) continue;
db t = a.f[j][i];
for(int k = 1 ; k <= N ; ++k) {
a.f[j][k] -= t * a.f[i][k];
b.f[j][k] -= t * b.f[i][k];
}
}
}
return b;
}
}A,B,C;
bool match(int u) {
for(int i = 1 ; i <= N ; ++i) {
if(g[u][i]) {
if(!vis[i]) {
vis[i] = 1;
if(!matc[i] || match(matc[i])) {
matc[i] = u;matk[u] = i;
return true;
}
}
}
}
return false;
}
void Solve() {
read(N);
for(int i = 1 ; i <= N ; ++i) {
for(int j = 1 ; j <= N ; ++j) {
scanf("%lf",&A.f[i][j]);
}
}
for(int i = 1 ; i <= N ; ++i) {
for(int j = 1 ; j <= N ; ++j) {
scanf("%lf",&C.f[i][j]);
}
}
B = ~A;
if(flag) {
puts("NIE");return;
}
C = C * B;
for(int i = 1 ; i <= N ; ++i) {
for(int j = 1 ; j <= N ; ++j) {
if(fabs(C.f[i][j]) > 1e-8) {
g[j][i] = 1;
}
}
}
for(int i = 1 ; i <= N ; ++i) {
memset(vis,0,sizeof(vis));
if(!match(i)) {
puts("NIE");return;
}
}
puts("TAK");
for(int i = 1 ; i <= N ; ++i) {
for(int j = 1 ; j <= N ; ++j) {
if(!g[i][j]) continue;
if(matk[i] == j) break;
if(matc[j] < i) continue;
memset(vis,0,sizeof(vis));
for(int k = 1 ; k < i ; ++k) vis[matk[k]] = 1;
vis[j] = 1;
int t = matk[i];
matc[t] = 0;
if(match(matc[j])) {
matk[i] = j;matc[j] = i;
break;
}
else {
matc[t] = i;
}
}
}
for(int i = 1 ; i <= N ; ++i) {
out(matk[i]);enter;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Solve();
return 0;
}
【BZOJ】3168: [Heoi2013]钙铁锌硒维生素的更多相关文章
- BZOJ 3168: [Heoi2013]钙铁锌硒维生素 [线性基 Hungary 矩阵求逆]
3168: [Heoi2013]钙铁锌硒维生素 题意:给一个线性无关组A,再给一个B,要为A中每个向量在B中选一个可以代替的向量,替换后仍然线性无关.判断可行和求字典序最小的解 PoPoQQQ orz ...
- 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不为 ...
- 洛谷 P4100 [HEOI2013]钙铁锌硒维生素 解题报告
P4100 [HEOI2013]钙铁锌硒维生素 题目描述 银河队选手名单出来了!小林,作为特聘的营养师,将负责银河队选手参加 宇宙比赛的饮食. 众所周知,前往宇宙的某个星球,通常要花费好长好长的时间, ...
- 【BZOJ3168】[Heoi2013]钙铁锌硒维生素 高斯消元求矩阵的逆+匈牙利算法
[BZOJ3168][Heoi2013]钙铁锌硒维生素 Description 银河队选手名单出来了!小林,作为特聘的营养师,将负责银河队选手参加宇宙比赛的饮食.众所周知,前往宇宙的某个星球,通常要花 ...
- BZOJ 3168 Luogu P4100 [HEOI2013]钙铁锌硒维生素 (矩阵求逆、二分图匹配)
线性代数+图论好题. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3168 (luogu) https://www.lu ...
- BZOJ3168. [HEOI2013]钙铁锌硒维生素(线性代数+二分图匹配)
题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3168 题解 首先,我们需要求出对于任意的 \(i, j(1 \leq i, j \leq ...
- BZOJ3168: [Heoi2013]钙铁锌硒维生素
设$A^TC=B^T$,这样$C_{ij}$表示$B_j$的线性表出需要$A_i$,那么$B_j$可以替换$A_i$,根据$C=(A^T)^{-1}B^T$求出$C$.要求字典序最小完美匹配,先求任意 ...
- bzoj 3165: [Heoi2013]Segment 动态凸壳
3165: [Heoi2013]Segment Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 202 Solved: 89[Submit][Stat ...
随机推荐
- 如何解决每次打开office 都会出现正在配置的问题
原因:安装offiece的时候直接选择以前安装过的office文件夹,导致文件冲突 解决方法:卸载,然后对准备要安装的文件夹清空或者重新建个新文件夹安装
- AtCoder Grand Contest 007
AtCoder Grand Contest 007 A - Shik and Stone 翻译 见洛谷 题解 傻逼玩意 #include<cstdio> int n,m,tot;char ...
- 洛谷 P3629 [APIO2010]巡逻 解题报告
P3629 [APIO2010]巡逻 题目描述 在一个地区中有 n 个村庄,编号为 1, 2, ..., n.有 n – 1 条道路连接着这些村 庄,每条道路刚好连接两个村庄,从任何一个村庄,都可以通 ...
- (转)Maven学习总结(一)——Maven入门 安装使用
备注 转自: 孤傲苍狼 http://www.cnblogs.com/xdp-gacl/p/3498271.html 只为成功找方法,不为失败找借口! 1. Maven的基本概念 Maven(翻译为& ...
- Spring MVC 向页面传值-Map、Model和ModelMap
原文链接:https://www.cnblogs.com/caoyc/p/5635878.html Spring MVC 向页面传值-Map.Model和ModelMap 除了使用ModelAndVi ...
- node.js原生后台进阶(二)
上一章讲到怎么样用原生node.js来获取GET.POST(urlencoded,formData)的参数,这一次我们更进一步,讲一下以下的点: 1.压缩(zlib) 2.流(stream) 3.路由 ...
- LRN
转自https://blog.csdn.net/u011204487/article/details/76026537 LRN全称为Local Response Normalization,即局部响应 ...
- Java基础-零拷贝技术应用案例
Java基础-零拷贝技术应用案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 零拷贝技术在Hadoop生态圈中很多组件得到应用,典型的比如kafka组件,它就很成功的应用了零拷贝 ...
- ASP.NET私有构造函数作用
一.私有构造函数的特性 1.一般构造函数不是私有或者保护成员,但构造函数可以使私有成员函数,在一些特殊的场合,会把构造函数定义为私有或者保护成员. 2.私有构造函数是一种特殊的实例构造函数.它通常用在 ...
- CSS-3 box-shadow 的使用
box-shadow是给对象实现图层阴影效果的. 语法: E {box-shadow: <length> <length> <length>?<length& ...