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 ...
随机推荐
- hdu_5104 Primes Problem()
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5104 rimes Problem Time Limit: 2000/1000 MS (Java/Oth ...
- hbmy周赛1--B
B - 改革春风吹满地 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit ...
- Zabbix如何实现批量监控端口状态
引言 ------------------------------------------------------------------------------------------------- ...
- Java简历与面试
尊重原创:http://blog.csdn.net/love_java_cc/article/details/78292347 Java就业指导 想要成为合格的Java程序员或工程师到底需要具备哪 ...
- sublimeserver启动本地服务器(sublime text)
今天又get到了一个新知识点,就是在sublime text上也可以模拟一个本地服务器的环境,前提是要先安装sublimeserver这个插件.这个插件的安装办法有两种. 1.我们可以直接在subli ...
- element-ui中upload组件如何传递文件及其他参数
最近项目用到了vuethink,里面集成了element-ui,之前一直用的是bootstrap框架,对js也是一知半解,然后也用过vue.js,但也是学的不通透的,然后就各种入坑. 下面就分析一下我 ...
- thinkphp发送邮件需要开启什么设置
邮件配置 'THINK_EMAIL' => array( 'SMTP_HOST' => 'smtp.163.com', //SMTP服务器 'SMTP_PORT' => '465', ...
- TP传输的两种模式
主动模式(active): 我们知道,FTP是由TCP封包的模式连接,TCP 这种封包由于需要经过 Server 端与 Client 端两边的『三次握手』之后,才能确定联机,也就是需要执行AC ...
- C语言第二次实验报告
1.实验题目 题1:11-7 找鞍点(20 分) 一个矩阵元素的"鞍点"是指该位置上的元素值在该行上最大.在该列上最小. 本题要求编写程序,求一个给定的n阶方阵的鞍点 题2: ...
- struts配置json需要的jar包