CF652E Pursuit For Artifacts 边双连通分量+缩点
一.题目
传送门
翻译:
给定一张 n个点 m条边的简单无向连通图,边有边权,边权要么为 0,要么为 1。
每条边只能通过一次(两个方向加起来只能通过一次)。
求是否存在一条从 a 到 b 的路径,满足路径上至少存在一条权为 1 的边。
二.题解
这道题目一眼边双连通分量,只要一个边双连通分量内有边权为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;
}
浙公网安备 33010602011771号