题目大意:给你一个无向图,问我们最多加一条边使得图的桥的数量最小,输出最小数量
解题思路:先将图缩点,我们就得到一个无环图,然后我们只需找到最长链,将其首尾相连即可减少对多的桥,减少的数量为链的长度,即树的直径。(ps:注释部分为并查集缩点)
代码:
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<queue>
#include<cmath>
#include<algorithm>
using namespace std;
#define inf 0x3fffffff
//const double pi=acos(-1);
typedef long long LL;
#define N 100005
int low[N],pre[N],scc[N],dfs_clock,scc_cnt;
int fa[N];
int cnt;
int ans;
int root;
struct node
{
int st,en,next;
//bool fg;
} e[2*N],e1[2*N];
int p[N],num;
void init()
{
memset(p,-1,sizeof(p));
num=0;
}
void add(int st,int en)
{
e[num].st=st;
e[num].en=en;
//e[num].fg=false;
e[num].next=p[st];
p[st]=num++;
}
int p1[N],num1;
void init1()
{
memset(p1,-1,sizeof(p1));
num1=0;
}
void add1(int st,int en)
{
e1[num1].st=st;
e1[num1].en=en;
e1[num1].next=p1[st];
p1[st]=num1++;
}
//int Find(int x)
//{
// if(fa[x]!=x)
// fa[x]=Find(fa[x]);
// return fa[x];
//}
//void Union(int u,int v)
//{
// int x=Find(u);
// int y=Find(v);
// if(x!=y)
// {
// fa[y]=x;
// }
//}
stack<int>s;
int dfs(int u,int fa)
{
pre[u]=low[u]=++dfs_clock;
s.push(u);
for(int i=p[u]; i+1; i=e[i].next)
{
int v=e[i].en;
if(!pre[v])
{
low[v]=dfs(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>pre[u])
{
// e[i].fg=1;
// e[i^1].fg=1;
cnt++;
}
// else
// {
// Union(u,v);
// }
}
else if(pre[v]<pre[u]&&v!=fa)
{
low[u]=min(low[u],pre[v]);
}
}
if(low[u]==pre[u])
{
scc_cnt++;
while(1)
{
int x=s.top();
s.pop();
scc[x]=scc_cnt;
if(u==x)
break;
}
}
return low[u];
}
void find_scc(int n)
{
dfs_clock=cnt=scc_cnt=0;
memset(pre,0,sizeof(pre));
for(int i=0;i<=n;i++)
fa[i]=i;
dfs(1,-1);
}
int dfs1(int st,int fa,int tem)
{
if(ans<tem)
{
ans=tem;
root=st;
}
for(int i=p1[st]; i+1; i=e1[i].next)
{
int en=e1[i].en;
if(en==fa)continue;
dfs1(en,st,tem+1);
}
return root;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
init();
init1();
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
{
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
find_scc(n);
if(cnt==0)
{
printf("0\n");
continue;
}
//int tot=num;
int xx;
// for(int i=0;i<tot;i++)
// {
// if(e[i].fg)
// {
// int u=Find(e[i].st);
// int v=Find(e[i].en);
// add1(u,v);
// xx=u;
// }
// }
for(int i=1; i<=n; i++)
{
for(int j=p[i]; j+1; j=e[j].next)
{
int en=e[j].en;
if(scc[i]!=scc[en])
{
add1(scc[i],scc[en]);
//add1(scc[en],scc[i]);
}
}
}
ans=0;
int x=dfs1(1,-1,0);
ans=0;
dfs1(x,-1,0);
printf("%d\n",cnt-ans);
}
return 0;
}