首页 > 其他分享 >[ABC318G] Typical Path Problem 题解

[ABC318G] Typical Path Problem 题解

时间:2023-09-03 20:22:04浏览次数:35  
标签:ABC318G std 10 题解 valueType back iter low Path

题意

给定一个 \(N\) 个节点和 \(M\) 条边组成的简单无向联通图,给定三个节点 \(A,B,C\),求是否存在一条简单路径满足 \(A \rightarrow B \rightarrow C\)。

(\(3 \le N, M \le 2 \times 10^5\))。

题解

因为简单路径要求每个节点至多经过一次,故不存在合法的简单路径当且仅当存在一个割点同时存在于路径 \(A \rightarrow B\) 和路径 \(B \rightarrow C\) 上。故建立圆方树后跑两遍 \(\tt{DFS}\) 即可,第一遍标记路径 \(A \rightarrow B\) 上的点,第二遍检查路径 \(B \rightarrow C\) 上是否有被标记且为割点的点。

总复杂度 \(\mathcal{O}(N + M)\),可以通过本题。

Code

#include <bits/stdc++.h>

typedef int valueType;
typedef std::vector<valueType> ValueVector;
typedef std::vector<ValueVector> ValueMatrix;
typedef std::vector<bool> bitset;

valueType N, M;
valueType A, B, C;

ValueVector dfn, low;
ValueMatrix G, tree, dcc;
bitset cut, path;
std::stack<valueType> S;

void tarjan(valueType x, valueType from) {
    static valueType time = 0;

    dfn[x] = low[x] = ++time;

    S.push(x);

    valueType son = 0;

    for (auto const &iter: G[x]) {
        if (iter == from)
            continue;

        if (!dfn[iter]) {
            ++son;

            tarjan(iter, x);

            low[x] = std::min(low[x], low[iter]);

            if (low[iter] >= dfn[x]) {
                cut[x] = true;

                dcc.emplace_back();
                dcc.back().emplace_back(x);

                int y;

                do {
                    y = S.top();
                    S.pop();
                    dcc.back().emplace_back(y);
                } while (y != iter);
            }
        } else {
            low[x] = std::min(low[x], dfn[iter]);
        }
    }

    if (from == 0 && son == 1)
        cut[x] = false;
}

void build() {
    for (valueType i = 0; i < dcc.size(); ++i) {
        valueType const x = N + i + 1;

        for (auto const &iter: dcc[i]) {
            tree[x].push_back(iter);
            tree[iter].push_back(x);
        }
    }
}

bool dfs(valueType x, valueType from, valueType TOP) {
    if (x == TOP)
        return path[x] = true;

    for (auto const &iter: tree[x]) {
        if (iter == from)
            continue;

        if (dfs(iter, x, TOP))
            return path[x] = true;
    }

    return path[x] = false;
}

bool check(valueType x, valueType from, valueType TOP, bool &result) {
    if (x == TOP)
        return true;

    for (auto const &iter: tree[x]) {
        if (iter == from)
            continue;

        if (check(iter, x, TOP, result)) {
            if (path[x] && cut[x])
                result = false;

            return true;
        }
    }

    return false;
}

int main() {
    std::cin >> N >> M;

    std::cin >> A >> B >> C;

    G.resize(N + 10);
    tree.resize(2 * N + 10);
    dfn.resize(N + 10, 0);
    low.resize(N + 10, 0);
    cut.resize(2 * N + 10, false);
    path.resize(2 * N + 10, false);

    for (valueType i = 0; i < M; ++i) {
        valueType u, v;

        std::cin >> u >> v;

        G[u].push_back(v);
        G[v].push_back(u);
    }

    tarjan(1, 0);

    build();

    dfs(A, 0, B);

    bool result = true;

    check(C, 0, B, result);

    if (result)
        std::cout << "Yes" << std::endl;
    else
        std::cout << "No" << std::endl;
}

标签:ABC318G,std,10,题解,valueType,back,iter,low,Path
From: https://www.cnblogs.com/User-Unauthorized/p/solution-ABC318G.html

相关文章

  • 【动态规划】“新手动态规划合集”题解
    动态规划三要素阶段,状态,决策动态规划经典模型LIS(最长上升子序列)给定长度为\(N\)的序列\(A[i]\),求出其最长上升子序列的长度。(以不严格上升为例)阶段:已经处理的序列长度\(i\)状态:\(f[i]\)表示以\(A[i]\)结尾的LIS长度转移\[f[i]=\max\limits_{j\in\left[1,......
  • [ABC318D] General Weighted Max Matching 题解
    [ABC318D]GeneralWeightedMaxMatching题解题意  给定无向有权完全图,求最大权匹配。思路分析  注意到\(n\le16\),我考虑状压DP。  设当前点集\(S\)中最大权匹配的答案是\(f_S\),我们考虑\(S\)中“最后”一个点\(p\)(这里的“最后”一个点是指,在状压表示状态......
  • [ABC318E] Sandwiches 题解
    题意给定一个长度为\(N\)的正整数列\(A=\left(A_1,A_2,\cdots,A_N\right)\),求满足以下条件的正整数三元组\(\left(i,j,k\right)\)的数量:\(1\lei<j<k\leN\);\(A_i=A_k\);\(A_i\neqA_j\)。数据范围:\(3\leN\le3\times10^5\);\(1\leA_i......
  • CF1848B Vika and the Bridge 题解
    CF1848BVikaandtheBridge题解题目大意给个题目传送门吧,感觉题意已经很清楚了题目传送门分析(我不会告诉你我第一眼看过去是二分)因为我们只能改一块木板的颜色,所以可以考虑贪心。大概算了下复杂度,也没有问题。题解我们要去求每种颜色最大距离的最小值,那我们可以先去求......
  • 有关Vue-Cli5.X工程中ESLint组件命名检查问题解决
    个人开发环境简介,工具用的VisualStudioCode,因为每个人的开发环境不同,不可能所有解决方案通用,防止踩坑。PSF:\VueWorkSpace\vue_router_test>node-vv16.12.0PSF:\VueWorkSpace\vue_router_test>npm-v8.1.0PSF:\VueWorkSpace\vue_router_test>npmeslint-v8.1.0......
  • P3604 美好的每一天题解
    传送门好题!首先说这道题的时间复杂度:\(O(26n\sqrtn)\)。因为转移是的常数是\(O(26)\)并非\(O(1)\),这启示我们,看数据范围,不要被O(1)给限制了,O(1)是一般情况,有些题不一般首先,回文串能出现的条件是所有的字符都出现偶数次\(or\)仅有一个字符出现奇数次,所以我们并不关心每个......
  • ABC318G Typical Path Problem
    给定无向连通图,问是否存在一条从\(A\)到\(C\)经过\(B\)的简单路径。\(n\le3\times10^5\)。怎么这个G这么简单我还没写完啊?怎么这个G这么简单我还没写完啊?怎么这个G这么简单我还没写完啊?怎么这个G这么简单我还没写完啊?怎么这个G这么简单我还没写完啊?怎么这......
  • 【题解】AtCoder Beginner Contest 318(D - Ex)
    赛时过了A-G,Ex仿佛猜到了结论但是完全不懂多项式科技,就炸了。大家好像都秒了A,B,C就不写了。D.GeneralWeightedMaxMatching题目描述:给你一个加权无向完全图,图中有\(N\)个顶点,编号从\(1\)到\(N\)。连接顶点\(i\)和\(j\)的\((i<j)\)的权重为\(D_{i,j}\)。在......
  • P4198 楼房重建题解
    传送门一眼数据结构。考虑线段树,记录该区间能看到最多的建筑数量\(ans_{wz}\)以及看到区间中最大的斜率(或者说,该区间内最后看到的建筑)\(xl_{wz}\)。很明显,假如我现在的修改操作是\((x,y)\),那么会改变\(\log_n\)个节点,即包含\(x\)的节点,考虑如何修改他们的\(ans\)和\(......
  • AT_abc318_e 题解
    AT_abc318_eSandwiches题解Links洛谷AtCoderDescription给定一个长度为\(n\)的序列\(a\),找到满足以下条件的三元组\((a,b,c)\)的数量。\(i<j<k\);\(a_{i}=a_{k}\);\(a_{i}\neqa_{j}\)。数据范围:\(1\leqn\leq3\times10^{5}\),\(1\leqa_{i}\leqn......