#include <cstdio>
#include <cstring>
#include <algorithm>
#include <stack>

using namespace std;

const int N=10005;
const int M=30005;

int n, m;
int head[N], E=0; // graph
int dfn[N], low[N], ts=0; // tarjan
int root, ans=0;

struct Edge{
    int v, ne;
}e[M];

inline void add(int a, int b){
    e[E].v=b;
    e[E].ne=head[a];
    head[a]=E++;
} 

void tarjan(int u){
    dfn[u]=low[u]=++ts;
    int cnt=0; // 统计u节点的子树数量
    for(int i=head[u]; ~i; i=e[i].ne){
        int v=e[i].v;
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u], low[v]);
            if(low[v]>=dfn[u]) ++cnt; // v是u的子树节点
        }
        else low[u]=min(low[u], dfn[v]); // v不是u的子树节点, 更新low[u]
    }
    if(u!=root) ++cnt; // u不是根节点, 去掉u后形成的子树计算父节点所在的子树
    ans=max(ans, cnt);
}

int main(){
    while(scanf("%d%d", &n, &m), n||m){
        memset(dfn, 0x00, sizeof dfn);
        memset(low, 0x00, sizeof low);
        memset(head, -1, sizeof head);
        E=ts=0;
        while(m--){
            int a, b;
            scanf("%d%d", &a, &b);
            add(a, b);
            add(b, a);
        }
        ans=0; // 删除点后连通块最多可以分成几部分
        int cnt=0; // 统计连通块的个数
        // 枚举图中的根节点
        for(root=0; root<n; ++root){
            if(!dfn[root]){
                ++cnt;
                tarjan(root);
            }
        }
        printf("%d\n", ans+cnt-1);
    }

    return 0;
}