Skip to content

Commit

Permalink
11.19
Browse files Browse the repository at this point in the history
  • Loading branch information
dtcxzyw committed Nov 19, 2018
1 parent 5584f3d commit b49ae56
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 1 deletion.
3 changes: 3 additions & 0 deletions Review/Other/TricksAndIdeas.tex
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@ \subsection{cdq分治}
对于动态偏序问题,保证第一维按照时间偏序,递归合并时边计算影响边
进行归并排序,使其排序后位置从小到大,修改优先于查询(但仍然保证两集合间
的时间关系)。
\subsection{Kernelization}
\index{*TODO!Kernelization}
参见\url{https://www.zhihu.com/question/272303098/answer/367368615}。
\subsection{注意事项}
\begin{itemize}
\item 边读入边处理时千万不要跳出循环,若要跳出循环则需继续读入额外跳过无用数据。
Expand Down
2 changes: 1 addition & 1 deletion Review/Path/SMSSP.tex
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ \subsubsection{LLL优化}
\subsubsection{堆优化}
沿着LLL优化的思路:使用距离尽可能小的节点来松弛。使用堆就可以维护了。
\subsubsection{卡SPFA}
留坑待补。
留坑待补,参见\url{https://www.zhihu.com/question/292283275}
\index{*TODO!卡SPFA}
\subsection{Dijkstra}
使用二叉堆的最坏时间复杂度$O((V+E)\lg V)$,在稀疏图中表现良好。
Expand Down
1 change: 1 addition & 0 deletions Review/Recommendation.tex
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ \section{优秀资料}
\item CodeForces优秀文章 \url{http://codeforces.com/blog/entry/57282}
\item E-Maxx算法合集英文版 \url{https://cp-algorithms.com/}
\item OI-Wiki \url{https://github.com/24OI/OI-wiki/}
\item 知乎上OI相关文章收藏 \url{https://www.zhihu.com/collection/213577780}
\end{itemize}
177 changes: 177 additions & 0 deletions Source/Virtual Tree/4426.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
#include <algorithm>
#include <cstdio>
#include <cstring>
int read() {
int res = 0, c;
do
c = getchar();
while(c < '0' || c > '9');
while('0' <= c && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
return res;
}
const int size = 100050, vsiz = 50, mod = 998244353;
#define asInt64(x) static_cast<long long>(x)
struct Edge {
int to, nxt;
} E[size * 2];
int last[size], cnt = 0;
void addEdge(int u, int v) {
++cnt;
E[cnt].to = v, E[cnt].nxt = last[u];
last[u] = cnt;
}
bool flag[size], vis[size];
struct Info {
int u, v;
} VE[vsiz];
int ecnt = 0;
bool DFS(int u, int p) {
vis[u] = true;
int siz = 0;
for(int i = last[u]; i; i = E[i].nxt) {
int v = E[i].to;
if(v != p) {
if(vis[v]) {
flag[u] = true;
if(u < v) {
VE[ecnt].u = u, VE[ecnt].v = v;
++ecnt;
}
} else
siz += DFS(v, u);
}
}
if(siz >= 2)
flag[u] = true;
return siz | flag[u];
}
int add(int a, int b) {
a += b;
return a < mod ? a : a - mod;
}
struct Vec {
int x, y;
Vec() {}
Vec(int x, int y) : x(x), y(y) {}
Vec operator+(const Vec& rhs) const {
return Vec(add(x, rhs.x), add(y, rhs.y));
}
void operator*=(long long k) {
x = x * k % mod, y = y * k % mod;
}
void operator*=(const Vec& rhs) {
x = x * asInt64(rhs.x) % mod,
y = y * asInt64(rhs.y) % mod;
}
} k[size][2];
long long dot(const Vec& a, const Vec& b) {
return (asInt64(a.x) * b.x + asInt64(a.y) * b.y) %
mod;
}
struct VT {
struct Edge {
int to, nxt;
Vec a, b;
} E[vsiz];
int last[size], cnt;
VT() : cnt(0) {}
void addEdge(int u, int v, const Vec& a,
const Vec& b) {
++cnt;
E[cnt].to = v, E[cnt].nxt = last[u],
E[cnt].a = a, E[cnt].b = b;
last[u] = cnt;
}
} vt;
int dp[size][2];
int build(int u) {
vis[u] = true;
int link = 0;
dp[u][0] = dp[u][1] = 1;
for(int i = last[u]; i; i = E[i].nxt) {
int v = E[i].to;
if(!vis[v]) {
int lv = build(v);
if(lv) {
if(flag[u])
vt.addEdge(u, lv,
k[v][0] + k[v][1],
k[v][0]);
else
k[u][0] = k[v][0] + k[v][1],
k[u][1] = k[v][0], link = lv;
} else {
dp[u][0] = dp[u][0] *
asInt64(dp[v][0] + dp[v][1]) % mod;
dp[u][1] =
dp[u][1] * asInt64(dp[v][0]) % mod;
}
}
}
if(flag[u])
k[u][0] = Vec(1, 0), k[u][1] = Vec(0, 1),
link = u;
else
k[u][0] *= dp[u][0], k[u][1] *= dp[u][1];
return link;
}
int d[size];
void preDepth(int u) {
for(int i = vt.last[u]; i; i = vt.E[i].nxt) {
int v = vt.E[i].to;
d[v] = d[u] + 1;
preDepth(v);
}
}
bool cho[size][2];
Vec solve(int u) {
Vec res(cho[u][1] ? 0 : dp[u][0],
cho[u][0] ? 0 : dp[u][1]);
for(int i = vt.last[u]; i; i = vt.E[i].nxt) {
int v = vt.E[i].to;
Vec dpv = solve(v);
res *= Vec(dot(dpv, vt.E[i].a),
dot(dpv, vt.E[i].b));
}
return res;
}
int main() {
int n = read();
int m = read();
while(m--) {
int u = read();
int v = read();
addEdge(u, v);
addEdge(v, u);
}
DFS(1, 0);
memset(vis + 1, 0, sizeof(bool) * n);
flag[1] = true;
build(1);
preDepth(1);
for(int i = 0; i < ecnt; ++i)
if(d[VE[i].u] > d[VE[i].v])
std::swap(VE[i].u, VE[i].v);
int end = 1 << ecnt, ans = 0;
for(int i = 0; i < end; ++i) {
for(int j = 0; j < ecnt; ++j)
if(i & (1 << j))
cho[VE[j].u][1] = cho[VE[j].v][0] =
true;
else
cho[VE[j].u][0] = true;
Vec res = solve(1);
ans = add(ans, add(res.x, res.y));
for(int j = 0; j < ecnt; ++j)
if(i & (1 << j))
cho[VE[j].u][1] = cho[VE[j].v][0] =
false;
else
cho[VE[j].u][0] = false;
}
printf("%d\n", ans);
return 0;
}
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@
- [ ] LCT维护子树信息和边权信息
- [ ] 共价大爷游长沙技巧
- [ ] FFT字符串通配
- [ ] fractional cascading
# Compare
- [ ] 最大流算法效率比较
- [ ] 平衡树效率比较
Expand Down

0 comments on commit b49ae56

Please sign in to comment.