题意:无向图~有重边,问任意添加一条边后的桥有多少个,求最小个数。
分析:tarjan+缩点+构图+树的直径,昨天在重边的缩点上边wa了两个多小时。。。今天再看这个题,按照以前写2-sat的有向图的缩点做的。然后构造出个一个新图,可以两遍spfa的求出树的直径。然后相减就是结果了。。。在处理重边时,需要标记的是边的标号,而不是父亲的节点.(重边不是桥)。。
#pragma comment(linker,"/STACK:1000000000,1000000000")
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#define N 200010
#define M 2000010
#define CC(x,y) memset(x,y,sizeof(x))
#define inf 1<<29
using namespace std;
struct node
{
int y,ne,id;
} e[M],e1[M];
int h[N],vis[N],low[N],dfn[N],dis[N],i,j,k,m,n,x,y,z,ss,cou,ans,sum,tt,h1[N],k1;
int used[M],st[N],numB,id[N],stack[N],instack[N],top,bcnt,num,belong[N];
void add(int x,int y,int z)
{
e[k].y=y;
e[k].ne=h[x];
e[k].id=z;
h[x]=k++;
}
void add1(int x,int y)
{
e1[k1].y=y;
e1[k1].ne=h1[x];
h1[x]=k1++;
}
void tarjan(int x)
{
int i,j,k;
dfn[x]=low[x]=++num;
stack[++top]=x;
instack[x]=1;
for (int i=h[x]; i!=-1; i=e[i].ne)
{
if (!used[e[i].id])
{
used[e[i].id]=1;
j=e[i].y;
if (dfn[j]==0)
{
tarjan(j);
low[x]=min(low[j],low[x]);
}
else if (instack[j]) low[x]=min(low[j],low[x]);
}
}
if (dfn[x]==low[x])
{
bcnt++;
do
{
j=stack[top--];
instack[j]=0;
belong[j]=bcnt;//缩点
}
while (j!=x);
}
}
void spfa(int tt)
{
int s=tt;
for (i=1; i<=n; i++)
{
dis[i]=inf;
vis[i]=0;
}
vis[s]=1;
queue<int>q;
while (!q.empty())q.pop();
q.push(s);
dis[s]=0;
while (!q.empty())
{
x=q.front();
q.pop();
for (int i=h1[x]; i!=-1; i=e1[i].ne)
{
int y=e1[i].y;
if(dis[y]>dis[x]+1)
{
dis[y]=dis[x]+1;
if (!vis[y])
{
vis[y]=1;
q.push(y);
}
}
}
vis[x]=0;
}
cou=0;
ans=-1;
for (i=1; i<=bcnt; i++)
if (dis[i]>ans)
{
ss=i;
ans=dis[i];
}
}
void build()
{
int i,j,k;
for (i=1; i<=n; i++)
for (j=h[i]; j!=-1; j=e[j].ne)
{
k=e[j].y;
if (belong[i]!=belong[k])
add1(belong[i],belong[k]);
}
}
int main()
{
while (scanf("%d%d",&n,&m)&&n)
{
CC(h,-1);
k=0;
for (i=1; i<=m; i++)
{
scanf("%d%d",&x,&y);
if (x==y)continue;
add(x,y,i);
add(y,x,i);
}
CC(low,0);
CC(dfn,0);
CC(used,0);
k1=0;
CC(h1,-1);
top=num=bcnt=0;
for (i=1; i<=n; i++)
if (!dfn[i])tarjan(i);
build();
spfa(1);
spfa(ss);
printf("%d\n",bcnt-(ans+1));
}
return 0;
}