CF652E Pursuit For Artifacts 边双连通分量+缩点

一.题目

传送门
翻译:
给定一张 n个点 m条边的简单无向连通图,边有边权,边权要么为 0,要么为 1。
每条边只能通过一次(两个方向加起来只能通过一次)。
求是否存在一条从 a 到 b 的路径,满足路径上至少存在一条权为 1 的边。
1n,m3×1051≤n,m≤3×10^5

二.题解

这道题目一眼边双连通分量,只要一个边双连通分量内有边权为1的边,如果经过这个边双连通分量那么就一定可以经过边权为1的边。于是我们考虑边双连通分量缩点,既然只用求一组LCA,于是我直接选择暴力爬山,每次爬都统计经过的边双连通分量内有没有边权为1的边,经过的桥边权是否为1,就愉快地解决了。

三.Code

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#include <stack>
using namespace std;

#define M 300005

struct node {
    int u, v, w;
    node (){};
    node (int V, int W){
        v = V;
        w = W;
    }
}e[M];
int t, n, m, dfn[M], low[M], cnt, num, belong[M], a, b, dep[M], f[M], mx, val[M], d[M];
vector <node> G[M];
stack <int> s;

void Tarjan (int x, int fa){
    dfn[x] = low[x] = ++ cnt;
    s.push(x);
    for (int i = 0; i < G[x].size(); i ++){
        int tmp = G[x][i].v;
        if (tmp == fa)
            continue;
        if (! dfn[tmp]){
            Tarjan (tmp, x);
            low[x] = min (low[x], low[tmp]);
        }
        else{
            low[x] = min (low[x], dfn[tmp]);
        }
    }
    if (low[x] == dfn[x]){
        num ++;
        int v;
        do{
            v = s.top();
            s.pop();
            belong[v] = num;
        }while (v != x);
    }
}
void dfs (int x, int fa){
    dep[x] = dep[fa] + 1;
    f[x] = fa;
    for (int i = 0; i < G[x].size(); i ++){
        int tmp = G[x][i].v, tot = G[x][i].w;
        if (tmp != fa){
            val[tmp] = tot;
            dfs (tmp, x);
        }
    }
}
void clime (int &x, int maxdep){
    while (dep[f[x]] >= maxdep)
        mx = max (max (val[x], d[a]), mx), x = f[x];
}
int main (){
    scanf ("%d %d", &n, &m);
    for (int i = 1; i <= m; i ++){
        scanf ("%d %d %d", &e[i].u, &e[i].v, &e[i].w);
        G[e[i].u].push_back (node (e[i].v, e[i].w));
        G[e[i].v].push_back (node (e[i].u, e[i].w));
    }
    Tarjan (1, 0);
    for (int i = 1; i <= n; i ++)
        G[i].clear ();
    for (int i = 1; i <= m; i ++){
        if (belong[e[i].u] != belong[e[i].v]){
            G[belong[e[i].u]].push_back (node (belong[e[i].v], e[i].w));
            G[belong[e[i].v]].push_back (node (belong[e[i].u], e[i].w));
        }
        else{
            if (e[i].w)
                d[belong[e[i].u]] = 1;
        }
    }
    scanf ("%d %d", &a, &b);
    dfs (1, 0);
    a = belong[a], b = belong[b];
    if (dep[a] > dep[b])
        clime (a, dep[b]);
    if (dep[a] < dep[b])
        clime (b, dep[a]);
    while (a != b){
        mx = max (max (val[a], d[a]), mx);
        mx = max (max (val[b], d[b]), mx);
        a = f[a], b = f[b];
    }
    mx = max (mx, d[a]);
    if (mx)
        printf ("YES\n");
    else
        printf ("NO\n");
    return 0;
}

Thanks!

posted on 2020-08-21 09:10  PI_PJW  阅读(58)  评论(0)    收藏  举报

导航