#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int cnt = 1,l[100005],h[100005],nex[100005];
int num,p,stack[100005],low[100005],dfn[100005];
bool op[100005],op_sig[100005];//op_sig判断路径是否走过
int f,r,a,b,ans;
inline void add( int v1 , int v2 ) {
++ cnt;
l[cnt] = h[v1];
h[v1] = cnt;
nex[cnt] = v2;
++ cnt;
l[cnt] = h[v2];
h[v2] = cnt;
nex[cnt] = v1;
}
void tarjan( int now ) {
dfn[now] = low[now] = ++ num;
stack[++ p] = now;
op[now] = true;
for (int i = h[now]; i != 0; i = l[i]) {
if( op_sig[i] == false) {
if ( dfn[nex[i]] == 0 ) {
op_sig[i] = true;//2^1=3 3^1=2 ......
op_sig[i^1] = true;//4^1=5 5^1=4... ...
//标记now到nex[i]的路径已经走过
tarjan( nex[i] );
low[now] = min( low[now] , low[nex[i]] );
if ( low[nex[i]] > dfn[now] ) {
//只有这种情况是割边
ans++;
}
}
else {
if ( op[nex[i]] ) {
low[now] = min( low[now] , dfn[nex[i]] );
}
}
}
}
if ( dfn[now] == low[now] ) {
int temp;
do {
temp = stack[p];
op[temp] = false;
p --;
} while ( now !=temp );
}
return;
}
int main() {
scanf("%d%d",&f,&r);
for (int i = 1; i <= r; ++i){
scanf("%d%d",&a,&b);
add( a , b );
}
tarjan( 1 );
printf("%d\n",ans);
return 0;
}
标签:tarjan,int,割边,low,nex,cnt,now,op
From: https://www.cnblogs.com/jueqingfeng/p/17258698.html