ABC266 F(基环树)

题目链接

  题目大意:给nn边的无向图,要判断uv是否只存在一条简单路径。
  思路:
    看到nn可以想到基环树,也就是在一棵树上多连一条边是的树上出现一个环,其余的点都是在以这个环上的点为根的子树中。那么不难想到如果u,v是在同一棵子树中,那么肯定是仅有一条简单路径到达。但是如果是在不同的子树中的话,必定存在两条简单路径从uv,可以从环上的两边前往v,所以只需要判断u,v是不是在同一个子树中就可以了。
    首先是要找环,并且我们需要将这个环上的所有的点都记录下来,可以考虑用一个栈来将所有的节点都存到栈中,当找到了环之后,就将栈中所有的节点都打上标记。

int n; std::cin >> n; std::vector<std::vector<int>> adj(n + 1); for (int i = 1; i <= n; i++) { int u, v; std::cin >> u >> v; adj[u].push_back(v); adj[v].push_back(u); } std::vector<int> stk(n + 10); int idx = 0; std::vector<bool> vis(n + 1), cir(n + 1); bool flag = 0; std::function<void(int, int)> dfs1 = [&] (int u, int fa) -> void { if (!flag) stk[++idx] = u; vis[u] = true; for (auto& v : adj[u]) { if (v == fa) continue; if (!vis[v]) dfs1(v, u); else if (!flag){ while(stk[idx] != v) { cir[stk[idx--]] = true; } cir[v] = true; flag = true; } } if (!flag) idx--; }; dfs1(1, 0);

    要将所有判断两个节点是不是在同一个子树里面,就需要找到他们的根节点是哪一个,所以就先将环上节点的子树中的节点都连向根节点,考虑用并查集来实现。

std::vector<int> f(n + 1); std::iota(f.begin(), f.end(), 0); std::function<void(int, int, int)> dfs2 = [&] (int u, int fa, int top) -> void { f[u] = top; for (auto& v : adj[u]) { if (v == fa) continue; if (!cir[v]) dfs2(v, u, top); } }; for (int i = 1; i <= n; i++) { if (cir[i]) dfs2(i, 0, i); } int q; std::cin >> q; for (int i = 1; i <= q; i++) { int x, y; std::cin >> x >> y; std::cout << (f[x] != f[y] ? "No\n" : "Yes\n"); }

__EOF__

本文作者HoneyGrey
本文链接https://www.cnblogs.com/Haven-/p/16660955.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   浅渊  阅读(56)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示