边双连通分量
作者:
limuru
,
2024-10-20 15:31:00
,
所有人可见
,
阅读 2
#include<bits/stdc++.h>
using namespace std;
const int N=5010,M=20010;
int h[N],e[M],ne[M],idx;
int n,m;
int dfn[N],low[N],timestamp;
int stk[N],top;
int id[N],dcc_cnt;
bool is_bridge[N];
int d[N];
void add(int a,int b)
{
e[idx]=b;
ne[idx]=h[a];
h[a]=idx++;
}
void tarjan(int u,int from)
{
dfn[u]=low[u]=++timestamp;
stk[++top]=u;
for(int i=h[u];~i;i=ne[i])
{
int j=e[i];
if(!dfn[j])
{
tarjan(j,i);
low[u]=min(low[u],low[j]);
if(dfn[u]<low[j])
is_bridge[i]=is_bridge[i^1]=true;
}
else if(i!=(from^1))
{
low[u]=min(low[u],dfn[j]);
}
}
if(dfn[u]==low[u])
{
++dcc_cnt;
int y;
do
{
y=stk[top--];
id[y]=dcc_cnt;
}while(y!=u);
}
}
signed main()
{
cin>>n>>m;
memset(h,-1,sizeof h);
while(m--)
{
int a,b;
cin>>a>>b;
add(a,b);
add(b,a);
}
tarjan(1,-1);
for(int i=0;i<idx;i++)
{
if(is_bridge[i])d[id[e[i]]]++;
}
int cnt=0;
for(int i=1;i<=dcc_cnt;i++)
{
if(d[i]==1)
{
cnt++;
}
}
cout<<(cnt+1)/2<<endl;
return 0;
}