#include<cstdio> #include<iostream> using namespace std; const int MAXN=1e5,MAXM=1e6; struct Edge{ int from,to,nxt; }e[MAXM]; int head[MAXN],edgeCnt=1; void addEdge(int u,int v){ e[++edgeCnt].from=u; e[edgeCnt].to=v; e[edgeCnt].nxt=head[u]; head[u]=edgeCnt; } int dfn[MAXN],low[MAXN],dfnCnt=0; bool bridge[MAXM]; void tarjan(int x,int in_edge){ dfn[x]=low[x]=++dfnCnt; for(int i=head[x];i;i=e[i].nxt){ int nowV=e[i].to; if(!dfn[nowV]){ tarjan(nowV,i); if(low[nowV]>dfn[x]){ bridge[i]=bridge[i^1]=1; } low[x]=min(low[x],low[nowV]); }else if(i!=(in_edge^1)){ low[x]=min(low[x],dfn[nowV]); } } } int inDcc[MAXN]; void dfs(int x,int nowDcc){ inDcc[x]=nowDcc; for(int i=head[x];i;i=e[i].nxt){ int nowV=e[i].to; if(inDcc[nowV]||bridge[i])continue; dfs(nowV,nowDcc); } } int main(){ int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); addEdge(u,v); addEdge(v,u); } for(int i=1;i<=n;i++) if(!dfn[i])tarjan(i,0); int nowDcc=0; for(int i=1;i<=n;i++) if(!inDcc[i])dfs(i,++nowDcc); printf("%d\n",nowDcc); return 0; }