BZOJ 3168: [Heoi2013]钙铁锌硒维生素 [线性基 Hungary 矩阵求逆]
3168: [Heoi2013]钙铁锌硒维生素
题意:给一个线性无关组A,再给一个B,要为A中每个向量在B中选一个可以代替的向量,替换后仍然线性无关。判断可行和求字典序最小的解
PoPoQQQ orz
显然是一个二分图匹配的模型
A是一个线性基,用它把B中每个向量表示出来,那么\(B_i\)可以替换\(A_j\)当且仅当表示\(B_i\)用到了\(A_j\)
可是A并不是每一位独立,怎么求表示啊?
A和B可以看成两个矩阵(横向量组)
\(C*A=B \rightarrow C=B*A^{-1}\)
\(C_{i,j}=1\)说明表示\(B_i\)用到了\(A_j\),那么\(C^T\)就是这个二分图的邻接矩阵了
求矩阵的逆
这里说一种方法,对A进行高斯约当消元,右面的常数列换成单位矩阵。校园后,左面变成了单位矩阵,右面就是\(A^{-1}\)
二分图匹配字典序最小的解
求任意一个完美匹配,然后从1到n贪心选择字典序最小的解,方法和hungary类似,但是要比较匹配点和当前点的字典序
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
typedef unsigned long long ll;
const int N=305, P=1e9+7;
inline int read() {
char c=getchar(); int x=0, f=1;
while(c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
return x*f;
}
inline ll Pow(ll a, int b) {
ll ans=1;
for(; b; b>>=1, a=a*a%P)
if(b&1) ans=ans*a%P;
return ans;
}
inline void mod(int &x) {if(x<0) x+=P; else if(x>=P) x-=P;}
int n, g[N][N]; char s[N];
struct Matrix {
int a[N][N];
Matrix(){memset(a, 0, sizeof(a));}
int* operator [](int x) {return a[x];}
inline void im() {for(int i=1; i<=n; i++) a[i][i]=1;}
void print() {for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) printf("%d%c",a[i][j],j==n?'\n':' ');}
}a, b, c;
Matrix inverse(Matrix a) {
Matrix c; c.im();
for(int i=1; i<=n; i++) {
int r;
for(r=i; r<=n; r++) if(a[r][i]) break;
// r != n+1
if(r!=i) for(int j=1; j<=n; j++)
swap(a[i][j], a[r][j]), swap(c[i][j], c[r][j]);
ll inv = Pow(a[i][i], P-2);
for(int j=1; j<=n; j++)
a[i][j] = a[i][j]*inv%P, c[i][j] = c[i][j]*inv%P;
for(int k=1; k<=n; k++) if(k!=i) {
ll t = a[k][i]%P;
for(int j=1; j<=n; j++)
mod(a[k][j] -= a[i][j]*t%P), mod(c[k][j] -= c[i][j]*t%P);
}
}
return c;
}
Matrix operator *(Matrix a, Matrix b) {
Matrix c;
for(int i=1; i<=n; i++)
for(int k=1; k<=n; k++) if(a[i][k])
for(int j=1; j<=n; j++)
mod(c[i][j] += (ll)a[i][k]*b[k][j]%P);
return c;
}
int vis[N], le[N];
bool dfs(int u) {
for(int v=1; v<=n; v++)
if(!vis[v] && g[u][v]) {
vis[v]=1;
if(!le[v] || dfs(le[v])) {
le[v]=u;
return true;
}
}
return false;
}
bool dfs(int u, int now) {
for(int v=1; v<=n; v++)
if(!vis[v] && g[u][v]) {
vis[v]=1;
if(le[v]==now || (le[v]>now && dfs(le[v], now))) {
le[v]=u;
return true;
}
}
return false;
}
int main() {
freopen("in","r",stdin);
//freopen("ferrous.in","r",stdin);
//freopen("ferrous.out","w",stdout);
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();
c = b * inverse(a); //puts("c");c.print();
//Matrix t = a * inverse(a); puts("t"); t.print();
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) if(c[i][j]) g[j][i]=1;
for(int i=1; i<=n; i++) {
memset(vis, 0, sizeof(vis));
if(!dfs(i)) {puts("NIE"); return 0;}
}
puts("TAK");
for(int i=1; i<=n; i++) {
memset(vis, 0, sizeof(vis));
dfs(i, i);
}
for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) if(le[j]==i) printf("%d\n",j);
}
BZOJ 3168: [Heoi2013]钙铁锌硒维生素 [线性基 Hungary 矩阵求逆]的更多相关文章
- 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不为 ...
- 【BZOJ】3168: [Heoi2013]钙铁锌硒维生素
题解 Ca Fe Zn Se 显然我们既然初始矩阵就能通过线性变换变成单位矩阵,则该矩阵一定有逆 没有逆输出NIE 而且因为这些向量两两正交,则表示一个向量的时候表示方法唯一 那么我们求一个逆可以求出 ...
- 洛谷 P4100 [HEOI2013]钙铁锌硒维生素 解题报告
P4100 [HEOI2013]钙铁锌硒维生素 题目描述 银河队选手名单出来了!小林,作为特聘的营养师,将负责银河队选手参加 宇宙比赛的饮食. 众所周知,前往宇宙的某个星球,通常要花费好长好长的时间, ...
- 【BZOJ3168】[Heoi2013]钙铁锌硒维生素 高斯消元求矩阵的逆+匈牙利算法
[BZOJ3168][Heoi2013]钙铁锌硒维生素 Description 银河队选手名单出来了!小林,作为特聘的营养师,将负责银河队选手参加宇宙比赛的饮食.众所周知,前往宇宙的某个星球,通常要花 ...
- BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]
4568: [Scoi2016]幸运数字 题意:一颗带点权的树,求树上两点间异或值最大子集的异或值 显然要用线性基 可以用倍增的思想,维护每个点向上\(2^j\)个祖先这些点的线性基,求lca的时候合 ...
- BZOJ 4671 异或图 | 线性基 容斥 DFS
题面 Description 定义两个结点数相同的图 G1 与图 G2 的异或为一个新的图 G, 其中如果 (u, v) 在 G1 与 G2 中的出现次数之和为 1, 那么边 (u, v) 在 G 中 ...
- BZOJ 4004 [JLOI2015]装备购买 | 线性基
题目链接 Luogu P3265 题解 非常正常的线性基! 但是我不会线性基-- (吐槽:#define double long double 才过--) #include <cstdio> ...
- BZOJ.4516.[SCOI2016]幸运数字(线性基 点分治)
题目链接 线性基可以\(O(log^2)\)暴力合并.又是树上路径问题,考虑点分治. 对于每个点i求解 LCA(u,v)==i 时的询问(u,v),只需求出这个点到其它点的线性基后,暴力合并. LCA ...
随机推荐
- 对于hive使用的一点记录
最近一段时间因工作需要接触了一些hive上的使用!当然大部分都是比较基本的使用,仅当入门!各位看到有不足之处望多多指正! 废话不多说,开始: 首先是创建数据库 create database '数据库 ...
- Kubernetes存储之Persistent Volumes简介
简介 管理存储和管理计算有着明显的不同.PersistentVolume子系统给用户和管理员提供了一套API,从而抽象出存储是如何提供和消耗的细节.在这里,我们介绍两种新的API资源:Persiste ...
- [国嵌攻略][100][嵌入式Linux内核制作]
Linux内核制作步骤 1.清除原有配置 make distclean 2.配置内核 选择一个已有的配置文件简化配置 make menuconfig ARCH=arm 3.编译内核 ARCH指明处理器 ...
- [学习OpenCV攻略][004][播放AVI视频]
cvCreateFileCapture(文件路径) 创建一个影音文件录像机,返回值为CvCapture类型,用于读取视频文件 cvQuerFrame(视频) 将下一帧视频文件载入内存,当CvCaptu ...
- 番外篇--Moddule Zero启动模板
1.3 ABPZero - 启动模板 1.3.1 简介 使用ABP和moudle-zero开始一个新项目的最简单的方式是在模板页创建模板.记住要勾选 Include module zero. 在创建并 ...
- textarea自适应高度,div模仿textarea可编辑实现自适应高度,placeholder使用图标
1.textarea自适应高度,placeholder使用图标 自适应高度,有很多种办法: 1)jq: $("textarea").on("input",fun ...
- dig命令
dig(域信息搜索器)命令是一个用于询问 DNS 域名服务器的灵活的工具.它执行 DNS 搜索,显示从受请求的域名服务器返回的答复.多数 DNS 管理员利用 dig 作为 DNS 问题的故障诊断, ...
- mdb文件怎么打开
(一)mdb格式的文件可以用MS Access打开编辑,也可以用Excel打开只能浏览. (二)mdb是什么文件格式 就像word的doc文件格式,mdb文件格式是Access数据库文件,微软Off ...
- -------- ROOTKIT 核心技术——系统服务调度表挂钩调试(PART III) --------
---------------------------------------------------------------------------------------- 本篇开始进行真枪实弹的 ...
- Spring Boot实战:拦截器与过滤器
一.拦截器与过滤器 在讲Spring boot之前,我们先了解一下过滤器和拦截器.这两者在功能方面很类似,但是在具体技术实现方面,差距还是比较大的.在分析两者的区别之前,我们先理解一下AOP的概念,A ...