bzoj3168
二分图+矩阵求逆
既然我们考虑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的更多相关文章
- 【BZOJ3168】[Heoi2013]钙铁锌硒维生素 高斯消元求矩阵的逆+匈牙利算法
[BZOJ3168][Heoi2013]钙铁锌硒维生素 Description 银河队选手名单出来了!小林,作为特聘的营养师,将负责银河队选手参加宇宙比赛的饮食.众所周知,前往宇宙的某个星球,通常要花 ...
- BZOJ3168: [Heoi2013]钙铁锌硒维生素
设$A^TC=B^T$,这样$C_{ij}$表示$B_j$的线性表出需要$A_i$,那么$B_j$可以替换$A_i$,根据$C=(A^T)^{-1}B^T$求出$C$.要求字典序最小完美匹配,先求任意 ...
- bzoj3168 钙铁锌硒维生素 (矩阵求逆+二分图最小字典序匹配)
设第一套为A,第二套为B 先对于每个B[i]判断他能否替代A[j],即B[i]与其他的A线性无关 设$B[i]=\sum\limits_{k}{c[k]*A[k]}$,那么只要看c[j]是否等于零即可 ...
- BZOJ3168. [HEOI2013]钙铁锌硒维生素(线性代数+二分图匹配)
题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3168 题解 首先,我们需要求出对于任意的 \(i, j(1 \leq i, j \leq ...
随机推荐
- ggplot2-为图形加入直线
本文更新地址:http://blog.csdn.net/tanzuozhev/article/details/51112057 本文在 http://www.cookbook-r.com/Graphs ...
- Mina、Netty、Twisted一起学(七):公布/订阅(Publish/Subscribe)
消息传递有非常多种方式.请求/响应(Request/Reply)是最经常使用的.在前面的博文的样例中.非常多都是採用请求/响应的方式.当server接收到消息后,会马上write回写一条消息到clie ...
- BZOJ 3727 PA2014 Final Zadanie 树形DP
题目大意:给定一棵树,令一个点到全部点的距离与点权的乘积之和为b[i].求每一个点的权值a[i] 首先假设给定a[i]我们能够非常轻松的求出b[i] 可是反过来怎么搞?高斯消元?30W? 考虑已知a[ ...
- HDU 3435A new Graph Game(网络流之最小费用流)
题目地址:HDU 3435 这题刚上来一看,感觉毫无头绪. .再细致想想.. 发现跟我做的前两道费用流的题是差点儿相同的. 能够往那上面转换. 建图基本差点儿相同.仅仅只是这里是无向图.建图依旧是拆点 ...
- c# 时间相关
1.求时间差,两种方式(时间是否小于1800秒) 第一种: DateTime startTime = DateTime.Now; ... DateTime.Now.Subtract(startTime ...
- Django小项目练习
Django学生管理系统 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^class_list/', views.class_list ...
- Selenium系列之--08 操作已打开的浏览器
Can Selenium interact with an existing browser session? 参考上面的文章 1. 建一个ReuseWebDriver类 import java.io ...
- POJ 1753 (枚举+DFS)
Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 40632 Accepted: 17647 Descr ...
- 修改live555支持mpeg2ts RTSP拉流,附代码
在很早之前的博客<用EasyDarwin进行IPTV rtsp mpeg-ts smil流的转发和分发直播服务>中,我们介绍到如何将live555支持mpeg2ts拉流,这个在IPTV领域 ...
- 安卓Android手机直播推送同步录像功能设计与实现源码
本文转自:http://blog.csdn.net/jyt0551/article/details/58714595 EasyPusher是一款非常棒的推送客户端.稳定.高效.低延迟,音视频同步等都特 ...