/* * ID: j.sure.1 * PROG: * LANG: C++ */ #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <ctime> #include <cmath> #include <stack> #include <queue> #include <vector> #include <map> #include <set> #include <string> #include <climits> #include <iostream> #define Mem(f, x) memset(f, x, sizeof(f)) #define PB push_back #define LL long long using namespace std; const int INF = 0x3f3f3f3f; const double eps = 1e-8; /****************************************/ const int N = 1e5, M = 1e5; struct Pair { int u, v; Pair(){} Pair(int _u, int _v): u(_u), v(_v){} }; struct Edge { int v, next; Edge(){} Edge(int _v, int _next): v(_v), next(_next){} }e[M]; int dfn[N], iscut[N], color[N], head[N]; stack <Pair> s; int bcc, deep; void add(int u, int v) { e[tot] = Edge(v, head[u]); head[u] = tot++; } int dfs(int u, int fa) { int lowu = dfn[u] = ++deep; int son = 0; for(int i = head[u]; ~i; i = e[i].next) { int v = e[i].v; Pair p = Pair(u, v); if(!dfn[v]) {//儿子 s.push(p);//和儿子的边进栈 son++; int lowv = dfs(v, u); lowu = min(lowu, lowv); if(lowv >= dfn[u]) {//条件成立时,说明走出关节点u会进入另一个连通分量 iscut[u] = 1; bcc++; while(1){ Pair x = s.top(); s.pop();//因此在此之前将u的所有分量染色 if(color[x.u] != bcc) color[x.u] = bcc; if(color[x.v] != bcc) color[x.v] = bcc; if(x.u == u && x.v == v) break; } } } else if(dfn[v] < dfn[u] && v != fa) {//回边 s.push(p); lowu = min(lowu, dfn[v]); } } if(fa == -1 && son == 1) iscut[u] = 0; return lowu; } void tarjan(int n) { for(int i = 0; i < n; i++) { dfn[i] = iscut[i] = color[i] = 0; head[i] = -1; } tot = deep = bcc = 0; for(int i = 0; i < n; i++) {//为防止图不连通 if(!dfn[i]) dfs(i, -1); } } int main() { #ifdef J_Sure freopen("000.in", "r", stdin); //freopen("999.out", "w", stdout); #endif return 0; }
时间: 2024-10-12 21:37:28