糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > BZOJ3168: [Heoi]钙铁锌硒维生素

BZOJ3168: [Heoi]钙铁锌硒维生素

时间:2018-08-23 02:48:03

相关推荐

BZOJ3168: [Heoi]钙铁锌硒维生素

传送门

题意

给定一个满秩的矩阵 AAA ,另一个矩阵 BBB

对于 AAA 的每个行向量 AiA_iAi​ 找到一个匹配 BBB 的行向量 BpiB_{p_i}Bpi​​

使得 AiA_iAi​ 替换成 BpiB_{p_i}Bpi​​ 后的矩阵 A′A'A′ 仍然满秩

Sol

如果 BpiB_{p_i}Bpi​​ 能替换 AiA_iAi​,那么说明存在一个向量 λ\lambdaλ 使得 λ×A′=Bpi\lambda \times A'=B_{p_i}λ×A′=Bpi​​

而 AAA 线性无关,只要 AAA 的元素表示 BpiB_{p_i}Bpi​​ 的线性组合中 AiA_iAi​ 的系数不为 000 就好了

所以只要求出系数矩阵 CCC,使得 C×A=BC\times A=BC×A=B

然后对于不为 000 的 Ci,jC_{i,j}Ci,j​,将 jjj 向 iii 连边,求这个二分图的字典序最小的完备匹配就好了

求 CCC 可以矩阵求逆实现,C=B×A−1C=B\times A^{-1}C=B×A−1

求二分图的字典序最小的完备匹配,可以先跑一遍匈牙利算法

然后在这个基础上再跑一次增广,贪心的匹配最小的,只改变匹配比当前点大的匹配边

# include <bits/stdc++.h>using namespace std;typedef long long ll;const int mod(10007);int a[305][605], b[305][305], d[305][305], c[305][305];int idx, n, ans, match[305], chos[305], cnt, vis[305];inline int Pow(int x, int y) {register int ret = 1;for (; y; y >>= 1, x = x * x % mod)if (y & 1) ret = ret * x % mod;return ret;}inline void GetInv() {register int i, j, k, inv, m = n + n;for (i = 1; i <= n; ++i) a[i][i + n] = 1;for (i = 1; i <= n; ++i) {for (j = i; j <= n; ++j)if (a[j][i]) {if (i != j) swap(a[i], a[j]);break;}inv = Pow(a[i][i], mod - 2);for (j = i; j <= m; ++j) a[i][j] = a[i][j] * inv % mod;for (j = 1; j <= n; ++j)if (i != j)for (inv = a[j][i], k = i; k <= m; ++k) a[j][k] = (a[j][k] - a[i][k] * inv % mod + mod) % mod;}for (i = 1; i <= n; ++i)for (j = 1; j <= n; ++j) d[i][j] = a[i][j + n];}inline void GetEdge() {register int i, j, k;for (i = 1; i <= n; ++i)for (j = 1; j <= n; ++j)for (k = 1; k <= n; ++k)(c[i][k] += b[i][j] * d[j][k] % mod) %= mod;}int Dfs(int u) {register int v;for (v = 1; v <= n; ++v)if (c[v][u] && vis[v] != idx) {vis[v] = idx;if (!match[v] || Dfs(match[v])) return chos[u] = v, match[v] = u, 1;}return 0;}int Change(int u, int rt) {register int v;for (v = 1; v <= n; ++v)if (c[v][u] && vis[v] != idx) {vis[v] = idx;if (!match[v] || (match[v] > rt && Change(match[v], rt))) return chos[u] = v, match[v] = u, 1;}return 0;}int main() {scanf("%d", &n);register int i, j;for (i = 1; i <= n; ++i)for (j = 1; j <= n; ++j) scanf("%d", &a[i][j]);for (i = 1; i <= n; ++i)for (j = 1; j <= n; ++j) scanf("%d", &b[i][j]);GetInv(), GetEdge();for (i = 1; i <= n; ++i) ++idx, ans += Dfs(i);if (ans != n) return puts("NIE"), 0;puts("TAK");for (i = 1; i <= n; ++i) ++idx, match[chos[i]] = 0, chos[i] = 0, Change(i, i);for (i = 1; i <= n; ++i) printf("%d\n", chos[i]);return 0;}

如果觉得《BZOJ3168: [Heoi]钙铁锌硒维生素》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。