题意:一个连通图,求添加一条边,使桥的数目最小
分析:tarjan求连通,缩点,因为是双向边,所以需要做一下标记,缩点之后重新构图,新的图必定是树,求树的直径,
添加一条边之后能使树的直径上的桥去掉,所以剩下桥的个数为原图中桥的个数减去树的直径。
在tarjan过程中求桥的个数,当dfn[u]<low[v]时,说明从点u到v之后不能再通过其他边访问到u,证明边u-v是桥
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
#define M 2000005
#define N 200005
#include<queue>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
struct edge{
int u,next,in_bridge;
}e[M];
struct node {
int x,step;
};
vector<int> v[N];
stack<int> s;
int vis[N],c,n,ans,cnt,index,head[N],low[N],dfn[N],instack[N],id[N],bridge;
void init(){
for(int i=1;i<=n;i++){
head[i]=-1;
dfn[i]=low[i]=0;
instack[i]=0;
v[i].clear();
}
while(!s.empty())
s.pop();
cnt=0;
index=0;
c=0;
ans=0;
bridge=0;
}
void addedge(int x,int y){
e[c].in_bridge=0;e[c].u=y;e[c].next=head[x];head[x]=c++;
e[c].in_bridge=0;e[c].u=x;e[c].next=head[y];head[y]=c++;
}
void tarjan(int u,int pre){
int flag=1;
low[u]=dfn[u]=++index;
instack[u]=1;
s.push(u);
int i,x;
for(i=head[u];i!=-1;i=e[i].next){
x=e[i].u;
if(x==pre&&flag){
flag=0;
continue;
}
if(!dfn[x]){
tarjan(x,u);
low[u]=min(low[u],low[x]);
if(dfn[u]<low[x]){
bridge++;
e[i].in_bridge=1;
e[i^1].in_bridge=1;
}
}else if(instack[x]){
low[u]=min(low[u],dfn[x]);
}
}
if(dfn[u]==low[u]){
++cnt;
do{
x=s.top();
s.pop();
id[x]=cnt;
instack[x]=0;
}while(u!=x);
}
}
int bfs(int u){
queue<node> q;
node now,next;
memset(vis,0,sizeof(vis));
now.step=0,now.x=u;
q.push(now);
vis[u]=1;
int mark=u;
while(!q.empty()){
now=q.front();
q.pop();
if(now.step>ans){
ans=now.step;
mark=now.x;
}
int u=now.x;
next.step=now.step+1;
for(int i=v[u].size()-1;i>=0;i--){
next.x=v[u][i];
if(!vis[next.x]){
vis[next.x]=1;
q.push(next);
}
}
}
return mark;
}
int main()
{
int m,i,j,x,y;
while(~scanf("%d%d",&n,&m)){
if(!n&&!m)
break;
init();
for(i=0;i<m;i++){
scanf("%d%d",&x,&y);
addedge(x,y);
}
tarjan(1,0);
for(i=1;i<=n;i++){
for(j=head[i];j!=-1;j=e[j].next){
x=i;y=e[j].u;
if(e[j].in_bridge){
v[id[x]].push_back(id[y]);
}
}
}
x=bfs(1);
y=bfs(x);
printf("%d\n",bridge-ans);
}
return 0;
}