题目大意:给出一个连通图,求再一个边后,剩余的最少桥数。
题目思路:首先进行缩点得到重构后的图,求出重构后树的直径(通过两次BFS求出相距最远的两点间的距离),ans=重构图边数-树的直径
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<vector>
#include<iostream>
#include<queue>
#include<algorithm>
#define MAXSIZE 200005
#define LL long long using namespace std; vector<vector<int> >G;
vector<vector<int> >G2;
int vis[MAXSIZE],low[MAXSIZE],dfn[MAXSIZE],pre[MAXSIZE],k,Time,n,m,ans,link;
int dist[MAXSIZE],belong[MAXSIZE],step[MAXSIZE],Stuck[MAXSIZE],block; void Tarjan(int u,int fa)
{
low[u]=dfn[u]=++Time;
pre[u]=fa;
Stuck[k++]=u;
int v,len=G[u].size(),op=;
for(int i=;i<len;i++)
{
v=G[u][i];
if(!op && v==fa)//去重边
{
op=;
continue;
}
if(!dfn[v])
{
Tarjan(v,u);
low[u]=min(low[u],low[v]);
}
else
{
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u])
{
int temp;
do{
temp=Stuck[--k];
belong[temp]=block;
}while(temp!=u);
block++;
}
} void Init()
{
memset(low,,sizeof(low));
memset(dfn,,sizeof(dfn));
memset(pre,,sizeof(pre));
memset(belong,,sizeof(belong));
memset(Stuck,,sizeof(Stuck));
ans=;
Time=;
block=;
k=;
G.clear();
G2.clear();
G.resize(n+);
G2.resize(n+);
} int BFS(int s,int op)
{
int now,next;
queue<int>Q;
memset(step,-,sizeof(step));
step[s]=;
Q.push(s);
while(!Q.empty())
{
now=Q.front();
Q.pop();
int len=G2[now].size();
for(int i=;i<len;i++)
{
next=G2[now][i];
if(step[next]==-)
{
step[next]=step[now]+;
Q.push(next);
}
}
} if(op==)
return now;
return step[now];
} int main()
{
int a,b;
while(scanf("%d%d",&n,&m),n+m)
{
Init();
for(int i=;i<=m;i++)
{
scanf("%d%d",&a,&b);
G[a].push_back(b);
G[b].push_back(a);
} for(int i=;i<=n;i++)
{
if(!dfn[i])
Tarjan(i,i);
} for(int i=;i<=n;i++)
{
int fa=pre[i];
if(belong[i] != belong[fa])
{
G2[belong[i]].push_back(belong[fa]);
G2[belong[fa]].push_back(belong[i]);
}
}
//两边BFS求出树的直径
int s=BFS(,);
int d=BFS(s,);
ans=block-d-;// 重构后的图的边数等于点数-1,根据贪心策略再减去重构树的直径就是答案
printf("%d\n",ans);
}
return ;
}