INOI2021 Day2T3 Andarzgu
Posted changle_cyx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了INOI2021 Day2T3 Andarzgu相关的知识,希望对你有一定的参考价值。
来源
https://www.noi.cn/xw/2021-05-31/729403.shtml
题意
给定一张 \\(n\\) 个点、\\(m\\) 条边的有向图,你需要选出一些点集互不相交的简单环(可以一个都不选),使得存在一种这些环的排列方式,存在一个点 \\(s\\),从 \\(s\\) 出发可以依次遍历这些环的所有点(注意,每个点可以经过多次,从一个环到下一个环经过的点没有要求)。
求选环的方案数的奇偶性。
\\(n \\leq 5000, m \\leq \\min \\left(10^6, \\binom n 2\\right)\\)。无重边无自环。
子任务:
- 忽略边的方向后,这张图是仙人掌。
- 这张图是强连通图。
题解
考虑子任务 2 怎么做。
选若干环的方案可以唯一映射到一个排列(毕竟排列可以分解为若干不相交的环,选择 \\((u,v)\\) 则排列中 \\(p_u=v\\),没选到的点则 \\(p_i=i\\)),且这个映射是个单射(不同的方案对应不同的排列)。
那么只要数出合法的排列数(可以被映射到的排列数)即可。显然,排列合法当且仅当 \\((i,p_i)\\in E\\),我们就在选环的方案和这些排列之间建立了双射。
即方案数就是邻接矩阵 \\(A\\) 加上单位矩阵 \\(I_n\\) 的积和式:
计算积和式是难以解决的。而我们只关心奇偶性,因此只要计算行列式的奇偶性(\\(\\sigma(p)\\) 表示 \\(p\\) 的逆序对数):
用 bitset 压位即可做到 \\(\\mathcal O\\left(\\frac{n^3}{\\omega}+n^2\\right)\\) 计算行列式。
对于一般图,我们只要将每个强连通分量运行如上算法得到方案数奇偶性,缩点后再按照拓扑序 DP 即可,用 bitset 实现传递闭包来处理转移合法性的判断。
时间复杂度 \\(\\mathcal O \\left( \\frac{n^3}{\\omega}+n^2+m \\right)\\)
#include <bits/stdc++.h>
using namespace std;
template <class T>
inline void read(T &x) {
static char ch;
while (!isdigit(ch = getchar()));
x = ch - \'0\';
while (isdigit(ch = getchar()))
x = x * 10 + ch - \'0\';
}
template <class T>
inline void tense(T &x, const T &y) {
if (x > y) x = y;
}
const int MaxN = 5000 + 5;
int n, m;
bool adj[MaxN][MaxN];
int dfsClock, dfn[MaxN], low[MaxN];
int top, stk[MaxN];
int nScc, scc[MaxN], valScc[MaxN];
vector<int> verScc[MaxN];
bitset<5000> mat[5000];
int det(int n) {
for (int i = 0; i < n; ++i) {
int p = -1;
for (int j = i; j < n; ++j)
if (mat[j][i]) {
p = j;
break;
}
if (p == -1)
return 0;
if (p != i)
swap(mat[i], mat[p]);
for (int j = i + 1; j < n; ++j)
if (mat[j][i]) {
mat[j] ^= mat[i];
}
}
return 1;
}
void tarjan(int u) {
stk[++top] = u;
dfn[u] = low[u] = ++dfsClock;
for (int v = 1; v <= n; ++v)
if (adj[u][v]) {
if (!dfn[v]) {
tarjan(v);
tense(low[u], low[v]);
} else if (!scc[v]) {
tense(low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) {
++nScc;
do {
int v = stk[top--];
scc[v] = nScc;
verScc[nScc].push_back(v);
// cerr << v << \' \'; //
} while (stk[top + 1] != u);
vector<int> &V = verScc[nScc];
for (int i = 0; i < (int)V.size(); ++i) {
mat[i].reset();
for (int j = 0; (int)j < V.size(); ++j)
mat[i][j] = adj[V[i]][V[j]];
mat[i][i] = 1;
}
valScc[nScc] = det(V.size()) ^ 1;
}
}
int main() {
#ifdef orzczk
freopen("andarzgu.in", "r", stdin);
freopen("andarzgu.out", "w", stdout);
#endif
read(n), read(m);
for (int i = 1; i <= m; ++i) {
int u, v;
read(u), read(v);
assert(u != v);
assert(!adj[u][v]);
adj[u][v] = 1;
}
for (int i = 1; i <= n; ++i)
if (!dfn[i])
tarjan(i);
int res = 1;
static int f[MaxN];
static bitset<MaxN> vis[MaxN];
for (int i = nScc; i >= 1; --i) {
vis[i][i] = 1;
for (int u : verScc[i]) {
for (int v = 1; v <= n; ++v)
if (adj[v][u] && scc[v] != scc[u]) {
vis[i] |= vis[scc[v]];
}
}
f[i] = valScc[i];
if (valScc[i]) {
for (int j = i + 1; j <= nScc; ++j)
if (vis[i][j])
f[i] ^= f[j];
}
res ^= f[i];
}
puts(res ? "Mistletoe: Time to go home!" : "Daddy: We should have a date...");
return 0;
}
以上是关于INOI2021 Day2T3 Andarzgu的主要内容,如果未能解决你的问题,请参考以下文章
Vijos1910 NOIP2014提高组 Day2T3 解方程 其他
刷题总结——mayan游戏(NOIP2011提高组day2T3)
洛谷P1084 [NOIP2012提高组Day2T3]疫情控制
Plasm部署智能合约——nginx反代转发plasm节点服务——2021.6.2
Plasm部署智能合约——nginx反代转发plasm节点服务——2021.6.2
java.sql.SQLException: Bad format for DATE ‘1 综治部门1 xieyirongheisastillnessman 2021-07-103001(代