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 矩阵求逆]的更多相关文章

  1. BZOJ 3168 Heoi2013 钙铁锌硒维生素 矩阵求逆+匈牙利算法

    题目大意:给定一个n∗n的满秩矩阵A和一个n∗n的矩阵B.求一个字典序最小的1...n的排列a满足将随意一个Ai换成Bai后矩阵A仍然满秩 我们考虑建立一个二分图.假设Ai能换成Bj.就在i−> ...

  2. BZOJ 3168 [Heoi2013]钙铁锌硒维生素 ——矩阵乘法 矩阵求逆

    考虑向量ai能否换成向量bj 首先ai都是线性无关的,然后可以a线性表出bj c1*a1+c2*a2+...=bj 然后移项,得 c1/ci*a1+...-1/ci*bj+...=ai 所以当ci不为 ...

  3. 【BZOJ】3168: [Heoi2013]钙铁锌硒维生素

    题解 Ca Fe Zn Se 显然我们既然初始矩阵就能通过线性变换变成单位矩阵,则该矩阵一定有逆 没有逆输出NIE 而且因为这些向量两两正交,则表示一个向量的时候表示方法唯一 那么我们求一个逆可以求出 ...

  4. 洛谷 P4100 [HEOI2013]钙铁锌硒维生素 解题报告

    P4100 [HEOI2013]钙铁锌硒维生素 题目描述 银河队选手名单出来了!小林,作为特聘的营养师,将负责银河队选手参加 宇宙比赛的饮食. 众所周知,前往宇宙的某个星球,通常要花费好长好长的时间, ...

  5. 【BZOJ3168】[Heoi2013]钙铁锌硒维生素 高斯消元求矩阵的逆+匈牙利算法

    [BZOJ3168][Heoi2013]钙铁锌硒维生素 Description 银河队选手名单出来了!小林,作为特聘的营养师,将负责银河队选手参加宇宙比赛的饮食.众所周知,前往宇宙的某个星球,通常要花 ...

  6. BZOJ 4568: [Scoi2016]幸运数字 [线性基 倍增]

    4568: [Scoi2016]幸运数字 题意:一颗带点权的树,求树上两点间异或值最大子集的异或值 显然要用线性基 可以用倍增的思想,维护每个点向上\(2^j\)个祖先这些点的线性基,求lca的时候合 ...

  7. BZOJ 4671 异或图 | 线性基 容斥 DFS

    题面 Description 定义两个结点数相同的图 G1 与图 G2 的异或为一个新的图 G, 其中如果 (u, v) 在 G1 与 G2 中的出现次数之和为 1, 那么边 (u, v) 在 G 中 ...

  8. BZOJ 4004 [JLOI2015]装备购买 | 线性基

    题目链接 Luogu P3265 题解 非常正常的线性基! 但是我不会线性基-- (吐槽:#define double long double 才过--) #include <cstdio> ...

  9. BZOJ.4516.[SCOI2016]幸运数字(线性基 点分治)

    题目链接 线性基可以\(O(log^2)\)暴力合并.又是树上路径问题,考虑点分治. 对于每个点i求解 LCA(u,v)==i 时的询问(u,v),只需求出这个点到其它点的线性基后,暴力合并. LCA ...

随机推荐

  1. cf_514C(字符串哈希)

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=121897#problem/G Watto and Mechanism Time ...

  2. mysql 手册关于修改列字符编码的一个bug

    项目因为历史原因使用了 GBK编码,遇到非GBK编码字符时出现乱码问题,情况比较严重,暂时先打算修改 列的字符编码为 utf8mb4. 查看 mysql 手册: 用 GBK 编码转 utf8 进行说明 ...

  3. 如何动态修改网页的标题(title)?

    有时候我们需要复用一个页面,但是又希望他们拥有各自的标题,这时候就需要动态的去更改页面的title了,不然所有页面都是一个标题. 这时候就会想到使用js或jQuery去实现了. 1.js方式. 首先, ...

  4. Oracle_SQL92_连接查询

    Oracle_SQL92_连接查询   笛卡儿积 --笛卡尔积 select * from emp;----14 select * from dept;----4 select * from emp, ...

  5. Sqoop介绍

    Sqoop介绍 http://sqoop.apache.org http://sqoop.apache.org/docs/1.4.6/SqoopUserGuide.html   1.什么是Sqoop? ...

  6. python利用socketserver实现并发套接字功能

    本文实现利用python的socketserver这个强大的模块实现套接字的并发 目录结构如下: 测试文件请放在server_file文件夹里面 server.py #!/usr/bin/env py ...

  7. WPF 简单的循环GIF播放

    //MVVM要事件绑定,记得项目引用类库“Sysrem.Windows.interactivity”,然后XAML引用 xmlns:i="http://schemas.microsoft.c ...

  8. encodeURIComponent() 函数

    https://baike.baidu.com/item/encodeURIComponent() 函数/7418815?fr=aladdin encodeURIComponent() 函数[1] 作 ...

  9. php 邓士鹏

    // $is_company = $_groupid > 5 || ($_groupid == 4 && $user['regid'] > 5); $_E = ($MOD[ ...

  10. 【开发技术】常用正则表达式大全!(例如:匹配中文、匹配html)

    匹配中文字符的正则表达式: [u4e00-u9fa5]   评注:匹配中文还真是个头疼的事,有了这个表达式就好办了 匹配双字节字符(包括汉字在内):[^x00-xff] 评注:可以用来计算字符串的长度 ...