二分图+矩阵求逆

既然我们考虑b能替换哪些a,那么我们自然要得出b被哪些a表示,这里我们设一个矩阵C,那么C*A = B

为什么呢?直接A*C = B是不可行的,因为都是行向量,不能直接乘,那么我们转置一下,得出At*C=Bt,这样就很科学了,那么再转回来,A*Ct=B,于是Ct=B*A^-1那么矩阵求逆就能得出Ct,于是我们再转置回来就能得出B是由哪些A表示的,然后跑二分图匹配就行了。

二分图匹配理解的不是很清楚,大概是不能用之前已经用过较小的编号来更新自己,还是看CQzhangyu的吧。

矩阵求逆用取模就行了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = ;
const ll P = ;
int rd()
{
int x = , f = ; char c = getchar();
while(c < '' || c > '') { if(c == '-') f = -; c = getchar(); }
while(c >= '' && c <= '') { x = x * + c - ''; c = getchar(); }
return x * f;
}
ll power(ll x, ll t)
{
ll ret = ;
for(; t; t >>= , x = x * x % P)
if(t & )
ret = ret * x % P;
return ret;
}
void up(ll &x, const ll &t)
{
x = ((x + t) % P + P) % P;
}
int n;
int vis[N], Map[N][N], match[N];
struct Matrix {
ll a[N][N];
Matrix() { memset(a, , sizeof(a)); }
void set() { for(int i = ; i <= n; ++i) a[i][i] = ; }
Matrix friend operator * (const Matrix &a, const Matrix &b) {
Matrix ret;
for(int i = ; i <= n; ++i)
for(int k = ; k <= n; ++k) if(a.a[i][k])
for(int j = ; j <= n; ++j)
up(ret.a[i][j], a.a[i][k] * b.a[k][j] % P);
return ret;
}
Matrix Inverse()
{
Matrix c;
c.set();
for(int i = ; i <= n; ++i)
{
int now = i;
while(now <= n && !a[now][i]) ++now;
for(int j = ; j <= n; ++j)
{
swap(a[now][j], a[i][j]);
swap(c.a[now][j], c.a[i][j]);
}
ll Inv = power(a[i][i], P - );
for(int j = ; j <= n; ++j)
{
a[i][j] = a[i][j] * Inv % P;
c.a[i][j] = c.a[i][j] * Inv % P;
}
for(int k = ; k <= n; ++k) if(k != i)
{
ll t = ((P - a[k][i] % P) % P + P) % P;
for(int j = ; j <= n; ++j)
{
a[k][j] = ((a[k][j] + t * a[i][j] % P) % P + P) % P;
c.a[k][j] = ((c.a[k][j] + t * c.a[i][j] % P) % P + P) % P;
}
}
}
return c;
}
void print()
{
for(int i = ; i <= n; ++i)
{
for(int j = ; j <= n; ++j) printf("%d ", a[i][j]);
puts("");
}
}
} a, b, c, d;
bool dfs(int u)
{
for(int i = ; i <= n; ++i) if(!vis[i] && Map[u][i])
{
vis[i] = ;
if(!match[i] || dfs(match[i]))
{
match[i] = u;
return true;
}
}
return false;
}
bool dfs(int u, int lev)
{
for(int i = ; i <= n; ++i) if(!vis[i] && Map[u][i])
{
vis[i] = ;
if(match[i] == lev || (match[i] > lev && dfs(match[i], lev)))
{
match[i] = u;
return true;
}
}
return false;
}
int main()
{
// freopen("ferrous.in", "r", stdin);
// freopen("ferrous.out", "w", stdout);
n = rd();
for(int i = ; i <= n; ++i)
for(int j = ; j <= n; ++j)
a.a[i][j] = rd();
for(int i = ; i <= n; ++i)
for(int j = ; j <= n; ++j)
b.a[i][j] = rd();
c = b * a.Inverse();
for(int i = ; i <= n; ++i)
for(int j = ; j <= n; ++j) if(c.a[i][j])
Map[j][i] = ;
int ans = ;
for(int i = ; i <= n; ++i)
{
memset(vis, , sizeof(vis));
ans += dfs(i);
}
if(ans < n)
{
puts("NIE");
return ;
}
for(int i = ; i <= n; ++i)
{
memset(vis, , sizeof(vis));
dfs(i, i);
}
puts("TAK");
for(int i = ; i <= n; ++i)
for(int j = ; j <= n; ++j) if(match[j] == i)
printf("%d\n", j);
// fclose(stdin);
// fclose(stdout);
return ;
}

bzoj3168的更多相关文章

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

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

  2. BZOJ3168: [Heoi2013]钙铁锌硒维生素

    设$A^TC=B^T$,这样$C_{ij}$表示$B_j$的线性表出需要$A_i$,那么$B_j$可以替换$A_i$,根据$C=(A^T)^{-1}B^T$求出$C$.要求字典序最小完美匹配,先求任意 ...

  3. bzoj3168 钙铁锌硒维生素 (矩阵求逆+二分图最小字典序匹配)

    设第一套为A,第二套为B 先对于每个B[i]判断他能否替代A[j],即B[i]与其他的A线性无关 设$B[i]=\sum\limits_{k}{c[k]*A[k]}$,那么只要看c[j]是否等于零即可 ...

  4. BZOJ3168. [HEOI2013]钙铁锌硒维生素(线性代数+二分图匹配)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3168 题解 首先,我们需要求出对于任意的 \(i, j(1 \leq i, j \leq ...

随机推荐

  1. solaris用户与文件权限管理

    此文章已于 20:45:28 2015/3/22 重新发布到 zhuxuekui3 solaris用户与文件权限管理1 类别    「网站分类」Oracle 一.用户与用户组管理 三种用户:超级用户. ...

  2. crtmp Server 开启rtsp服务功能

    Crtmp Server 包含了rtsp 服务功能,如果需要一个简单轻量的rtsp服务,Crtmp Server会是不错的选择. 默认情况下,rtsp功能是关闭的,需要在配置文件中打开.window环 ...

  3. PE发送报文

    步骤: 1. 在 action 中使用发送报文,要指定报文在 router 端的交易名称 2. 如果使用 supe.execute(context) 来发送,不需要第一步 3. 配置从网银到 rout ...

  4. [网页游戏开发]Morn简介及使用教程

    网页游戏开发利器,morn系列教程之Morn简介及使用教程 网页游戏开发的一大部分工作是在和UI制作上,一个好的工具及框架能使开发事半功倍,Adobe自带flash IDE和Flex各有不足. Mor ...

  5. SQL 游标示例

    DECLARE @i INT ) --给初始值 CREATE TABLE #temp_test --创建临时表 ( num ) ) ) BEGIN INSERT INTO #temp_test ( n ...

  6. c# 怎么获取自己的IP地址

    1.aspx页面,asp.net项目的页面 <%@ Page Language="C#" AutoEventWireup="true" CodeBehin ...

  7. 修改JDK环境变量,不生效的问题

    一般是在/etc/profile下面配置JDK的环境变量 JAVA_HOME=/data/jdk1.7.0_72 JRE_HOME=/data/jdk1.7.0_72/jre PATH=$PATH:$ ...

  8. C/C++笔记之char *与wchar_t *的相互转换

    char *和wchar_t *的相互转换,可使用标准库函数 size_t mbstowcs(wchar_t *wcstr, const char *mbstr, size_t count)和size ...

  9. iOS信号量

    引子: 在取本地联系人列表的时候看到同事用的这么一段代码: dispatch_semaphore_t sema = dispatch_semaphore_create(); ABAddressBook ...

  10. h5 placeholder 设置无效

    下面设置方式无效: ::-webkit-input-placeholder { /* WebKit browsers */ color: #999; } :-moz-placeholder { /* ...