【边双】CF Edu10 E

Problem - E - Codeforces

题意:

 

思路:

st 到 ed存在多条路径

注意到在同一个边双连通分量中,如果存在一条边的边权是1,那么这个边双连通分量中所有点对的路径中都存在一条边的边权是1,因此我们考虑缩点,缩完点之后是一棵树,这样路径就唯一了。只需要看 st的分量 到 ed的分量 的路径中是否存在边权是1的边即可

Code:

#include <bits/stdc++.h>

#define int long long
#define lowbit(x) (x & (-x))

using i64 = long long;

constexpr int N = 2e6 + 10;
constexpr int M = 2e6 + 10;
constexpr int P = 2e6;
constexpr i64 Inf = 1e18;
constexpr int mod = 1e9 + 7;
constexpr double eps = 1e-6;

std::stack<int> S;
std::vector<std::array<int,3> > E(M);
std::vector<std::array<int, 2> > adj[N], adj2[N];

bool ok = false;
int n, m, u, v, w, st, ed;
int tot = 0, cnt = 0;
int dfn[N], low[N], vis[N], bl[N], vis2[N], can[N];

void tarjan(int u, int fa) {
    dfn[u] = low[u] = ++tot;
    S.push(u);
    vis[u] = 1;
    for (auto [v, w] : adj[u]) {
        if (v == fa) continue;
        if (!dfn[v]) {
            tarjan(v, u);
            low[u] = std::min(low[u], low[v]);
        }else if (vis[v]) low[u] = std::min(low[u], low[v]);
    }

    if (dfn[u] == low[u]) {
        bl[u] = ++cnt;
        while(S.top() != u) {
            bl[S.top()] = cnt;
            vis[S.top()] = 0;
            S.pop();
        }
        S.pop();
        vis[u] = 0;
    }
}
void dfs(int u, int fa, int f) {
    if (can[u]) f = 1;
    if (u == bl[ed]) {
        if (f == 1) ok = true;
    }
    for (auto [v, w] : adj2[u]) {
        if (v == fa) continue;
        if (!vis2[v]) {
            vis2[v] = 1;
            dfs(v, u, f | w);
            vis2[v] = 0;
        }
    }
}
void solve() {
    std::cin >> n >> m;
    for (int i = 1; i <= m; i ++) {
        std::cin >> u >> v >> w;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
        E[i] = {u, v, w};
    }

    tarjan(1, 0);
    for (int i = 1; i <= m; i ++) {
        if (bl[E[i][0]] == bl[E[i][1]] && E[i][2]) {
            can[bl[E[i][0]]] = 1;
        }
    }

    for (int i = 1; i <= m; i ++) {
        if ((bl[E[i][0]] != bl[E[i][1]])) {
            adj2[bl[E[i][0]]].push_back({bl[E[i][1]], E[i][2]});
            adj2[bl[E[i][1]]].push_back({bl[E[i][0]], E[i][2]});
        }
    }

    std::cin >> st >> ed;
    st = bl[st];
    dfs(st, 0, 0);
    if (ok == true) {
        std::cout << "YES" << "\n";
    }else {
        std::cout << "NO" << "\n";
    }
}
signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int t = 1;

    while (t--) {
        solve();
    }
    
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值