首先用tarlen算法缩点
缩点后形成一颗树
我们要形成一个2重连通图
即就把只有一条边与图连接的点连起来
(其实只用统计一下 入/出度 就可以了,我的dfs判断复杂辣,但是既然也可以AC,就不改啦 )
给出代码:
#include<bits/stdc++.h>
using namespace std;
int n,m,a,b;
struct oppo {
int to,nest;
} rood[20004];
int head[5005],tot;
void add(int from,int to) {
rood[++tot].to=to;
rood[tot].nest=head[from];
head[from]=tot;
}
int dfn[5005],low[5005],time_,vis[5005],all;
int belong[5005];
stack< int > v;
void Ta(int x,int fa) {
dfn[x]=low[x]=++time_;
v.push(x);
vis[x]=1;
for(int i=head[x]; i; i=rood[i].nest) {
if(rood[i].to==fa)
continue;
if(!dfn[rood[i].to]) {
Ta(rood[i].to,x);
low[x]=min(low[x],low[rood[i].to]);
} else
low[x]=min(low[x],low[rood[i].to]);
}
if(dfn[x]==low[x]) {
int y;
all++;
do {
y=v.top();
belong[y]=all;
v.pop();
} while(y!=x);
}
}
struct vivo {
int to,nest;
} e[20005];
int _head[5005],_tot,ans;
void _add(int from,int to) {
e[++_tot].to=to;
e[_tot].nest=_head[from];
_head[from]=_tot;
}
void dfs(int x,int fa) {
bool f=1;
for(int i=_head[x]; i; i=e[i].nest) {
if(e[i].to==fa)
continue;
f=0;
dfs(e[i].to,x);
}
if(f)
ans++;
}
bool f[5005][5005];
int main() {
cin>>n>>m;
for(int i=1; i<=m; i++) {
scanf("%d %d",&a,&b);
add(a,b);
add(b,a);
}
Ta(1,0);
for(int i=1; i<=n; i++)
for(int j=head[i]; j; j=rood[j].nest)
if(belong[i]!=belong[rood[j].to]&&!f[belong[i]][belong[rood[j].to]]) {
_add(belong[i],belong[rood[j].to]);
_add(belong[rood[j].to],belong[i]);
f[belong[rood[j].to]][belong[i]]=1;
f[belong[i]][belong[rood[j].to]]=1;
}
for(int i=1; i<=n; i++)
if(e[_head[i]].nest) {
dfs(i,0);
cout<<(ans+1)/2<<endl;
return 0;
}
puts("0");
return 0;
}
tarjanQWQ