#pragma comment(linker,"/STACK:102400000,102400000") #include <iostream> #include <queue> #include <cstdio> #include <vector> #include <cstring> #include <algorithm> using namespace std; const int maxn = 200100; const int maxm = 2000100; struct node{ int v,next; }edge[maxm]; struct Bridge { int u,v; }bridge[maxm]; int head[maxn],vis[maxm],fa[maxn],dfn[maxn],low[maxn],stack[maxn],in[maxn]; int id,time,num,total,top,ans; void add_edge(int u,int v) { edge[id].v = v;edge[id].next = head[u],head[u] = id++; edge[id].v = u;edge[id].next = head[v],head[v] = id++; } int min(int x,int y) { return x < y ? x : y; } void tarjan(int u) {//无向图找桥并缩点 low[u] = dfn[u] = ++time; stack[top++] = u; for(int id = head[u] ; id != -1; id = edge[id].next) { int v =edge[id].v; if(vis[id])continue; vis[id] = vis[id^1] = 1; if( !dfn[v] ) { tarjan(v); low[u] = min(low[u],low[v]); if( low[v] > dfn[u])//u经过v不能回到u,则u与v之间存在桥 { bridge[total].u = u; bridge[total++].v = v; } } low[u] = min(low[u],dfn[v]); } if(low[u] == dfn[u]) {//对连通分量进行缩点 num++; int t; do{ t = stack[--top]; fa[t] = num; }while( t != u); } } vector<int>g[maxn]; int dfs(int u) {//求树的最大直径 vis[u]=1; int i,j,temp=0,Max=0,lMax=0;//Max为以u为根,u到的最远的叶子节点的距离,lMax为次最远距离 for(i = 0; i < g[u].size() ; i++ ){ int v = g[u][i]; if(vis[v])continue; temp=dfs(v); if(temp+1>=Max){ lMax=Max; Max=temp+1; } else if(temp+1>lMax) lMax=temp+1; if(Max+lMax>ans) ans=Max+lMax; } return Max; } int max_len() {//求树的最大直径 int res = 0; memset(vis,0,sizeof(vis)); queue<int>que; que.push(1); vis[1] = 1; int tmp; while( !que.empty()) { int u = que.front(); que.pop(); tmp = u; for( int i = 0 ; i < g[u].size(); i++) { int v = g[u][i]; if( vis[v] )continue; vis[v] = 1; que.push(v); } } queue<pair<int,int> >que1; memset(vis,0,sizeof(vis)); que1.push(make_pair(tmp,0)); pair<int,int>x,y; vis[tmp] = 1; while( !que1.empty()) { x = que1.front(); que1.pop(); for(int i = 0; i < g[x.first].size() ; i++) { int v = g[x.first][i]; if( vis[v] )continue; vis[v] = 1; que1.push(make_pair(v,x.second+1)); res = res > x.second ? res : x.second + 1; } } return res; } int main() { int n,m,u,v; int i; // freopen("in.txt","r",stdin); while( ~scanf("%d%d",&n,&m) && n+m) { id = 0; memset(head,-1,sizeof(head)); while( m-- ) { scanf("%d%d",&u,&v); add_edge(u,v); } total = num = 0; memset(dfn,0,sizeof(dfn)); memset(fa,-1,sizeof(fa)); memset(vis,0,sizeof(vis)); for(i = 1; i <= n; i++)//可以处理不连通的无向图,如果连通只需要一次即可 { if( !dfn[i] ) { top = time = 1; tarjan(i); //num++; //for( int j = 1; j <= n; j++) //特殊处理顶点的连通块 // if( dfn[j] && fa[j] == -1)fa[j] = num; } } //for( i = 1; i <= n; i++)cout << fa[i] << endl; for(i = 1; i <= n;i++)g[i].clear(); int x,y; //建树 // cout << total << endl; for( i = 0 ; i < total; i++) { x = fa[bridge[i].u]; y = fa[bridge[i].v]; //cout << x << " " << y << endl; g[x].push_back(y); g[y].push_back(x); } memset(vis,0,sizeof(vis)); ans = 0; dfs(1); printf("%d ",total - ans ); } return 0; }