分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 运营维护

CF555E Case of Computer Network

发布时间:2023-09-06 02:08责任编辑:蔡小小关键词:暂无标签

传送门

题意

题解

容易发现,在同一个边双内的点我们是不用管它的,一定可以。

那么我们缩点,然后把图变成一颗树。这样,$s$ 到 $t$ 的路径就可以用$\mathrm{LCA}$求了。

我们把 $s$ 到 $\mathrm{LCA}$ 的路径打向上的标记,把 $\mathrm{LCA}$ 到 $t$ 的路径打向下的标记。

只要没有路径有两种标记,就是可以的。

打标记使用树上差分实现。时间复杂度:$\mathcal O\left(n+m+q\mathrm{lg}n\right)$。

附上代码:

#pragma GCC optimize(3)#include <bits/stdc++.h>using namespace std;#define down(x, y) x = min(x, y)int n, m, q;struct edge { ???int from, to, nxt, id;} edges[400005];struct edgE { ???int to, nxt;} edgEs[400005];int e0, e = 1, e2 = 1, hed[200005], hEd[200005], tim = 0, fa[200005], dfn[200005], low[200005], scc[200005], dis[200005], lca[18][200005];int flg[200005]; bool root[200005]; bool goon[200005];int leaves[200005], top=0;const int CLEAN_FLAG = 0x1;const int UP_FLAG = 0x2;const int DOWN_FLAG = 0x4;stack<int> S;inline bool hasflag(int x, int attr) { ???return flg[x] & attr;}inline bool setflag(int x, int attr) { ???if (attr == UP_FLAG && hasflag(x, DOWN_FLAG)) return false; ???if (attr == DOWN_FLAG && hasflag(x, UP_FLAG)) return false; ???flg[x] |= attr; ???return true;}inline void addedge(int x, int y) { ???edges[e] = (edge){x, y, hed[x], e2}; ???hed[x] = e++; ???edges[e] = (edge){y, x, hed[y], e2++}; ???hed[y] = e++;}inline void addedgE(int x, int y) { ???edgEs[e] = (edgE){y, hEd[x]}; ???hEd[x] = e++;}inline void _tarjan(int x) { ???dfn[x] = low[x] = ++tim; ???S.push(x); ???for (int e=hed[x]; e; e=edges[e].nxt) { ???????int y = edges[e].to; ???????if (edges[e].id == fa[x]) continue; ???????if (!dfn[y]) { ???????????fa[y] = edges[e].id; ???????????_tarjan(y); ???????????down(low[x], low[y]); ???????} else down(low[x], dfn[y]); ???} ???if (dfn[x] == low[x]) { ???????scc[x] = ++e2; ???????while (S.top() != x) { ???????????scc[S.top()] = e2; ???????????S.pop(); ???????} ???????S.pop(); ???}}inline void tarjan() { ???for (int i=1; i<=n; i++) if (!dfn[i]) _tarjan(i); ???for (int i = 0; i < e0; i++) { ???????int x = edges[i].from, y = edges[i].to; ???????if (scc[x] == scc[y]) continue; ???????addedgE(scc[x], scc[y]); ???}}inline void lca_pre() { ???for (int i=1; i<18; i++) ???????for (int j=1; j<=n; j++) ???????????lca[i][j] = lca[i-1][lca[i-1][j]];}inline int LCA(int x, int y) { ???if (dis[x] > dis[y]) swap(x, y); ???int u = dis[x], v = dis[y]; ???int X=x, Y=y; ???for (int det = v-u, i=0; det; det>>=1, ++i) ???????if (det & 1) Y = lca[i][Y]; ???if (X == Y) return X; ???for (int i=17; i>=0; i--) { ???????if (lca[i][X] == lca[i][Y]) continue; ???????X = lca[i][X]; Y = lca[i][Y]; ???} ???return lca[0][X];}int group[200005], current;inline void dfs(int x, int fa) { ???bool isleaf = true; group[x] = current; ???for (int e=hEd[x]; e; e=edgEs[e].nxt) { ???????int y = edgEs[e].to; ???????if (y != fa) { ???????????isleaf = false; ???????????lca[0][y] = x; ???????????dis[y] = dis[x] + 1; ???????????dfs(y, x); ???????} ???} ???if (isleaf) leaves[top++] = x;}inline bool akmachine(int x, int flag) { ???while (!root[x]) { ???????if (goon[x]) return true; ???????goon[x] = true; ???????if (hasflag(x, UP_FLAG) && !hasflag(x, CLEAN_FLAG) && (flag & DOWN_FLAG) ????????|| hasflag(x, DOWN_FLAG) && !hasflag(x, CLEAN_FLAG) && (flag & UP_FLAG)) ???????????return false; ???????if (hasflag(x, CLEAN_FLAG)) flag = 0; ???????flag = flg[x] & (UP_FLAG | DOWN_FLAG); ???????x = lca[0][x]; ???} ???return true;}inline bool check() { ???for (int i=0; i<top; i++) if (!akmachine(leaves[i], 0)) return false; ???return true;}inline bool solve() { ???for (int i=1; i<=n; i++) ???????if (!dis[i]) { ???????????current = i; lca[0][i] = i; root[i] = 1; ???????????dfs(i, 0); ???????} ???lca_pre(); ???while (q--) { ???????int s, t; cin >> s >> t; ???????s = scc[s]; t = scc[t]; ???????if (group[s] != group[t]) return false; ???????if (s == t) continue; ???????int p = LCA(s, t); ???????if (p != s) if (!setflag(s, UP_FLAG)) return false; ???????if (p != t) if (!setflag(t, DOWN_FLAG)) return false; ???????setflag(p, CLEAN_FLAG); ???} ???return check();}int main() { ???ios :: sync_with_stdio(false); cin.tie(0); ???cin >> n >> m >> q; ???for (int i=1; i<=m; i++) { ???????int x, y; cin >> x >> y; ???????addedge(x, y); ???} ???e0 = e; e = 1; e2 = 0; tarjan(); ???cout << (solve() ? "Yes" : "No") << endl; ???return 0;}

CF555E Case of Computer Network

原文地址:https://www.cnblogs.com/mchmch/p/codeforces-555E.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved