Unicom double edge component Tarjan Algorithms

definition

If no absence of a cutting edge connected graph, called the "double-edge connected graph." None called "double side connected component" to the maximum double side connected subgraphs of the connectivity graph, simply referred to as "e-DCC"

theorem

The picture shows a double-edge connected graph, if and only if any of the at least one side are contained in a simple ring.

Seeking

Figure delete all the bridges, and the rest are e-DCC.
Specific Method: General Tarjan labeled with all the bridge, and then determine the number of each of the communication blocks dfs (go without traversing bridge).
Condensing point and often with: the number of e-DCC as nodes, as a bridge between the nodes connected edges, will form a tree or a forest.

Example redundant paths

Classic applications - bis communication component configured edges: each edge is a bridge of the tree, but not directly connected to any different two points plus the two side lca thereto form a ring, all points on the edge ring is strongly connected. Since the subject of the request even minimal side, then the plus side of each side to allow more points strongly connected. Analysis of the ring structure found on more lca farther point from two contributions FIG. So every time you connect lca leaf farthest from two points. This problem does not require output scheme, because every time it
disappeared two leaf nodes then the answer directly (leaf nodes + 1) / 2. (Odd remaining edges connected to a point just other points).

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<algorithm>
#define lson x<<1
#define rson x<<1|1
#define ll long long
#define rint register int
#define mid ((st[x].l + st[x].r) >> 1)
using namespace std;
template <typename xxx> inline void read(xxx &x) {
    char c = getchar(),f = 1;x = 0;
    for(;c ^ '-' && !isdigit(c);c = getchar());
    if(c == '-') c = getchar(),f = -1;
    for(;isdigit(c);c = getchar()) x = (x<<1) + (x<<3) + (c ^ '0');
    x *= f;
}
template<typename xxx> inline void print(xxx x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) print(x/10);
    putchar(x%10+'0');
}
const int maxn = 200010;
const int inf = 0x7fffffff;
const int mod = 1e9 + 7;
struct edge{
    int to,last,fg,from;    
}e[maxn];
int head[maxn],tot;
inline void add(int from,int to) {
    ++tot;
    e[tot].to = to;
    e[tot].from = from;
    e[tot].last = head[from];
    head[from] = tot;
}
int n,m;
int dfn[maxn],low[maxn],cnt;
inline void tarjan(int x,int in_edge) {
    dfn[x] = low[x] = ++cnt;
    for(rint i = head[x];i; i = e[i].last) {
        if(!dfn[e[i].to]) {
            tarjan(e[i].to,i);
            if(low[e[i].to] < low[x]) low[x] = low[e[i].to];
            if(low[e[i].to] > dfn[x]) {
                e[i].fg = e[i^1].fg = 1;
            }
        }
        else if(i ^ (in_edge ^ 1) && dfn[e[i].to] < low[x]) low[x] = dfn[e[i].to];
    }
}
int col[maxn],num,in[maxn];
inline void ddfs(int x) {
    col[x] = num;
    for(rint i = head[x];i;i = e[i].last) {
        if(col[e[i].to] || e[i].fg) continue;
        ddfs(e[i].to);
    }
}
int main()
{
    read(n);read(m);tot = 1;
    for(rint i = 1;i <= m; ++i) {
        int x,y;
        read(x);read(y);
        add(x,y);add(y,x);
    }   
    for(rint i = 1;i <= n; ++i) {
        if(!dfn[i]) {
            tarjan(i,0);
        }
    }
    for(rint i = 1;i <= n; ++i) {
        if(!col[i]) {
            ++num;
            ddfs(i);
        }
    }
    for(rint i = 2;i <= tot; ++i) {
        if(col[e[i].from] == col[e[i].to]) continue;
        ++in[col[e[i].from]];
        ++in[col[e[i].to]];
    }
    int ans = 0;
    for(rint i = 1;i <= num; ++i) 
        if(in[i] == 2) ++ans;
    print((ans + 1) / 2);
    return 0;
}
/*

*/

Guess you like

Origin www.cnblogs.com/Thomastine/p/11783730.html