Tarjan algorithm of cutting edge

definition

(In the undirected graph): In a connected graph, wherein an edge if omitted, will increase the number of communication block, we called this edge or cutting edge of the bridge.

algorithm

Tarjan, determined only low [v]> dfn [u ] to (u parent, v sub)
Explanation: not to the point before the parent node if the parent or child node in the case does not go the same way, the sub node can only take the same route back to the parent node and before, the same way as the only way, broken Unicom will produce a new block, in line with the definition of cutting edge.

Examples HDU-4738

This question a lot of details.
FIG first determines whether the link, and then determine whether the bridge, heavy side of the note is determined that the interference the bridge, the final output of the right minimum edge bridge (if it is a 0 to be output, to send the at least one go)

#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>void print(xxx x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) print(x/10); 
    putchar(x%10+'0');
}
const int maxn = 2002;
const int inf = 0x7fffffff;
const int mod = 1e9 + 7;
struct edge {
    int to,last,val;
//  int fg;
}e[2000002];
int head[maxn],tot;
inline void add(int from,int to,int val) {
    ++tot;
    e[tot].to = to;
//  e[tot].fg = 0;
    e[tot].val = val;
    e[tot].last = head[from];
    head[from] = tot;
}
int n,m;
int dfn[maxn],low[maxn],cnt;
int mark[2000002],mk;
inline void tarjan(int x,int in_edge) {//通过in_edge到达x 
    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[x] > low[e[i].to]) low[x] = low[e[i].to];
            if(low[e[i].to] > dfn[x]) {//子节点无法到达我及我之前,则联系我与子节点的边为桥 
//这个判断可以防重边对桥的干扰,假设原图有一个桥,tarjan时绝对无法回到父节点及之前节点,
//但是有重边时 子节点通过重边“回到父节点”更新low[e[i].to] == dfn[x],结果无法被判为桥 
//              e[i].fg = e[i^1].fg = 1;//可这样记录重边 
                mark[++mk] = e[i].val;
            }
        }
        else if(i ^ (in_edge ^ 1) && dfn[e[i].to] < low[x]) low[x] = dfn[e[i].to];//保证无重边时不会被父亲更新 
    }
}
int main()
{
    while(1) {
        tot = 1;
        mk = 0;
        cnt = 0;
        read(n);read(m);
        if(!n && !m) break;
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        memset(head,0,sizeof(head));
        for(rint i = 1;i <= m; ++i) {
            int a,b,c;
            read(a);read(b);read(c);
            add(a,b,c);add(b,a,c);
        }   
        int k = 0;
        for(rint i = 1;i <= n; ++i) {
            if(!dfn[i]) {
                tarjan(i,0);
                ++k;
            }
        }
        if(mk == 0) {//无桥, 
            printf("-1\n");
        } else {
            stable_sort(mark + 1,mark + mk + 1);
            if(k > 1) printf("0\n");
            else if(mark[1])printf("%d\n",mark[1]);
            else printf("1\n");//没人守也要派一个人去占领 
        }
    }   
    return 0;
}
/*
6 8
1 2 1
2 1 2
1 3 3
3 4 4
4 1 5
2 5 6
2 6 7
5 6 8

6 7
1 2 1
1 3 3
3 4 4
4 1 5
2 5 6
2 6 7
5 6 8
*/

Guess you like

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