【题解/搜索】P6743 Senior Postmen
Starrykiller · · 题解
传送门
调了整整两天才过 qvq,在此感谢@北京大佬!
可以在 Starrykiller's blog 中阅读,或许会有更好的阅读体验。
题意简述
给出一张图,将其分成若干个环,其中这些环没有重复的边,且这些环覆盖了所有的点和边。
解法
考虑搜索。
我们有如下性质:若一个图的所有节点的度数均为偶数,则我们可以将这个图按题目要求分成不同的环。
我们不妨这么考虑:任选一个点作为起点进行 dfs(前提是经过的边没有访问过),并对访问过的边进行标记。
在 dfs 过程中,设当前点为
(1)dfs 完后(for 循环结束后),如果
大部分人可能用 while 来实现出栈的过程,需要注意的是,循环结束的时候,需要将栈顶的点(即点
最后将
(2)若
这样直到 dfs 结束,我们就将图按题目的要求分成了一些互不相交的环。
Tips
Special Judge
该题目的 SPJ 并不会自动忽略行末空格(除最后一个空行外),会导致判定数字时加上空格而“不符合数字的格式”从而 WA,需要特殊处理。
优化
(1)
考虑 dfs 的过程,当前节点为
(a)若 head[u]=nxt[u]。
(b)若 head[u]=nxt[u]。
综上,我们在每次 for 循环时令 head[u]=nxt[u]。另外注意 for 循环更新为 i=head[u],否则会导致效率大大降低。(TLE
(2)使用 bitset 存储 vis 数组,或许可以提高效率和减少空间开销。
(3)合理使用快读和快写。
其实最重要的是优化
代码
不要 copy 代码哦 www
const int MAXN=5e5+10, MAXM=1e6+10;
int n, m;
struct {
int nxt, to;
} e[MAXM]; int head[MAXN], tot=1; // 双向边优化
inline void add(int u, int v) {
e[++tot].to=v, e[tot].nxt=head[u], head[u]=tot;
}
bitset<MAXM> vis, in_stack;
int stk[MAXN], r;
inline void dfs(int u) { // 感谢rzy神!!!
for (int i=head[u]; i; i=head[u]) {
// 注意这里的循环赋值
int to=e[i].to;
head[u]=e[i].nxt; // 优化1
if (vis[i]) continue;
vis[i]=vis[i^1]=true;
dfs(e[i].to);
}
// 进出栈过程
if (in_stack[u]) {
while (stk[r]!=u && r) {
in_stack[stk[r]]=false;
write(stk[r--]); putchar(' ');
}
write(stk[r--]); putchar('\n'); // 本题专属的SPJ优化
}
else in_stack[u]=true;
stk[++r]=u;
}
int main() {
n=read(), m=read();
int x, y;
for (int i=1; i<=m; ++i) {
x=read(), y=read();
add(x,y), add(y,x);
}
dfs(1);
return 0;
}
这是 sk 酱的第一篇题解哦~
一定会有错误或者不足之处,欢迎大家指出,也请大家多多见谅 qaq
Reference
Solution on DM::OJ
Offical solution for BalticOI 2014 (虽然我没看懂)(悲)