1 #include <iostream>
2 #include <cstdio>
3 #include <cstdlib>
4 #include <cmath>
5 #include <algorithm>
6 #include <cstring>
7 #include <stack>
8 #include <cctype>
9 #include <queue>
10 #include <string>
11 #include <vector>
12 #include <set>
13 #include <map>
14 #include <climits>
15 #define lson root<<1,l,mid
16 #define rson root<<1|1,mid+1,r
17 #define fi first
18 #define se second
19 #define ping(x,y) ((x-y)*(x-y))
20 #define mst(x,y) memset(x,y,sizeof(x))
21 #define mcp(x,y) memcpy(x,y,sizeof(y))
22 #define Min(x,y) (x<y?x:y)
23 #define Max(x,y) (x>y?x:y)
24 using namespace std;
25 #define gamma 0.5772156649015328606065120
26 #define MOD 1000000007
27 #define inf 0x3f3f3f3f
28 #define N 11005
29 #define maxn 5005
30 typedef long long LL;
31 typedef pair<int,int> PII;
32
33 stack<int>sk;
34 int n,m,hcnt,deep,block,leaf;
35 int d[maxn],dfn[maxn],low[maxn],head[maxn];
36 int color[maxn],vis[maxn];
37 struct Node{
38 int to,next;
39 Node(){}
40 Node(int a,int b):to(a),next(b){}
41 }node[N<<1];
42
43 inline void add(int x,int y){
44 node[hcnt]=Node(y,head[x]);
45 head[x]=hcnt++;
46 }
47
48 inline void init(){
49 while(!sk.empty())sk.pop();
50 mst(vis,0);
51 mst(head,-1);
52 mst(d,0);
53 mst(dfn,0);
54 hcnt=deep=0;
55 block=leaf=0;
56 }
57
58 void dfs(int x,int fa){
59 int flag=1; ///这个不是必要的,有重边时有效
60 sk.push(x);
61 vis[x]=1;
62 low[x]=dfn[x]=++deep;
63 for(int i=head[x];~i;i=node[i].next){
64 int e=node[i].to;
65 if(e==fa&&flag){flag=0;continue;}
66 if(vis[e])low[x]=min(low[x],dfn[e]);
67 else if(!dfn[e]){
68 dfs(e,x);
69 low[x]=min(low[x],low[e]);
70 }
71 }
72 if(low[x]==dfn[x]){
73 ++block; ///缩点
74 int co;
75 do{
76 co=sk.top();sk.pop();
77 vis[co]=0;
78 color[co]=block;
79 }while(co!=x);
80 }
81 }
82
83 int main(){
84 int i,j,group,Case=0,x,y;
85 while(scanf("%d%d",&n,&m)!=EOF){
86 init();
87 for(i=0;i<m;++i){
88 scanf("%d%d",&x,&y);
89 add(x,y);
90 add(y,x);
91 }
92 for(i=1;i<=n;++i){
93 if(!dfn[i])dfs(i,-1);
94 }
95 if(block==1){printf("0\n");continue;} ///判断是否已经是双连通图
96 for(i=1;i<=n;++i)
97 for(j=head[i];~j;j=node[j].next){
98 int e=node[j].to;
99 if(color[i]!=color[e])
100 ++d[color[i]]; ///d数组保留的是缩点后每个点的度数
101 }
102 for(i=1;i<=block;++i){
103 if(d[i]==0)leaf+=2; ///如果有孤立的点,叶子节点加2
104 else if(d[i]==1)++leaf;
105 }
106 printf("%d\n",(leaf+1)/2);
107 }
108 return 0;
109 }