思路:用tarjan算出无向连通图的连通分量的个数,那么桥的个数也就是连通分量个数减一,将在同个连通分量内的点进行缩点,最后将不同连通分量之间连边,求一遍新图(是一棵树)的最长路径(树的直径),显然,最长的直径加上头尾一条边形成一个环,可以减少相同长度的桥,也就是加上一条边后,原图能达到最少的桥数。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define maxn 200005
#define maxm 2000005
struct Enode
{
int to,next;
} edge[maxm];
int head[maxn],esum;
int x[maxm],y[maxm];
int dfn[maxn],low[maxn],stack[maxn],belong[maxn],index,top,bcnt;
int dis[maxn],que[maxn];
bool vis[maxn],instack[maxn];
int n,m;
void init()
{
memset(head,-1,sizeof(head));
esum=0;
}
inline void add(int u,int v)
{
edge[esum].to=v,edge[esum].next=head[u],head[u]=esum++;
}
void bfs(int s)
{
memset(vis,0,sizeof(vis));
memset(dis,0,sizeof(dis));
int l,r,v,u;
l=r=0;
vis[s]=1;
dis[s]=0;
que[r++]=s;
while(r>l)
{
u=que[l++];
for(int i=head[u]; ~i; i=edge[i].next)
if(!vis[v=edge[i].to])
{
vis[v]=1;
dis[v]=dis[u]+1;
que[r++]=v;
}
}
}
int treediameter(int s)
{
int u,maxl;
bfs(s);
maxl=0,u=s;
for(int i=1; i<=n; i++)
if(dis[i]>maxl)
u=i,maxl=dis[i];
bfs(u);
maxl=0;
for(int i=1; i<=n; i++)
if(dis[i]>maxl)
maxl=dis[i];
return maxl;
}
void tarjan(int now,int pre)
{
int v;
dfn[now]=low[now]=++index;
instack[now]=true;
stack[++top]=now;
for (int i=head[now]; ~i; i=edge[i].next)
{
v=edge[i].to;
if(i==pre) continue;
if (!dfn[v])
{
tarjan(v,i^1);
if (low[v]<low[now])
low[now]=low[v];
}
else if (instack[v] && dfn[v]<low[now])
low[now]=dfn[v];
}
if (dfn[now]==low[now])
{
bcnt++;
do
{
v=stack[top--];
instack[v]=false;
belong[v]=bcnt;
}
while (v!=now);
}
}
void solve()
{
int i;
top=bcnt=index=0;
memset(dfn,0,sizeof(dfn));
for (i=1; i<=n; i++)
if (!dfn[i])
tarjan(i,-1);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
if(!n&&!m) break;
init();
for(int i=0; i<m; i++)
{
scanf("%d%d",&x[i],&y[i]);
add(x[i],y[i]);
add(y[i],x[i]);
}
solve();
init();
for(int i=0; i<m; i++)
if(belong[x[i]]!=belong[y[i]])
{
add(belong[x[i]],belong[y[i]]);
add(belong[y[i]],belong[x[i]]);
}
int maxlen=treediameter(1);
printf("%d\n",bcnt-1-maxlen);
}
return 0;
}