Description
小X所居住的X国共有n个城市,有m条无向道路将其连接。作为一个统一的国家,X 城的任意两个城市都可以相互到达。
由于X国正处于地震带上,有时X国中会有至多一条道路发生毁坏,无法使用。如果这条道路的毁坏恰好阻断了某些城市的往来,那么我们称这条道路是危险的。
人们并不喜欢危险的道路,于是人们决定重建恰好一条道路,以减少危险的道路数。请告诉人们,重建恰好一条道路后,危险的道路数最少是多少。
Input
输入文件包含多组数据,对于每一组数据,第一行两个整数n,m,表示X 国的城市数与道路数。
接下来m 行,每行两个整数x,y,描述一条道路。
输入文件以n = 0,m = 0 结尾。
保证输入的图是一张连通图,但不保证不存在重边与自环。
Output
对于每一组数据,输出一行一个整数,表示危险的道路数的最小值。
Sample Input
5 6
1 2
2 1
1 3
2 4
4 4
5 2
0 0
Sample Output
1
样例解释:
一种最优的重建方式是连接城市3,5,这样,只有道路(2,4)是危险的。
数据范围
题解
先看看哪一些边是安全的,
就是说它被删掉之后,并不会影响连通性,
也就是环里面的边。
既然是环,就先tarjan缩点。
这样图就变成了树,
用贪心的思想,
如何加一条边,构成树中最大的环,
找直径。
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#define ll long long
#define N 200003
using namespace std;
char ch;
void read(int& n)
{
n=0;
for(ch=getchar();ch<'0' || ch>'9';ch=getchar());
for(;'0'<=ch && ch<='9';n=(n<<3)+(n<<1)+ch-48,ch=getchar());
}
struct node
{
int x,y;
}a[N*5];
int n,m,x,y,nxt[N*10],b[N],to[N*10],tot;
int dfn[N],low[N],z[N],f[N],cnt,top,id;
int nxt1[10*N],b1[N],to1[10*N];
int mx,pos;
bool bz[N],w[N];
int min(int x,int y){return x<y?x:y;}
int max(int x,int y){return x>y?x:y;}
void ins(int x,int y)
{
nxt[++tot]=b[x];
to[tot]=y;
b[x]=tot;
}
void ins1(int x,int y)
{
nxt1[++tot]=b1[x];
to1[tot]=y;
b1[x]=tot;
}
void dfs(int x,int len)
{
bz[x]=0;
if(len>mx)mx=len,pos=x;
for(int i=b1[x];i;i=nxt1[i])
if(bz[to1[i]])dfs(to1[i],len+1);
}
void tarjan(int x,int fa)
{
dfn[x]=low[x]=++id;
bz[x]=0;w[x]=1;
z[++top]=x;
for(int i=b[x];i;i=nxt[i])
{
if(i==(fa^1))continue;
if(bz[to[i]])
{
tarjan(to[i],i);
low[x]=min(low[x],low[to[i]]);
}else if(w[x])low[x]=min(low[x],dfn[to[i]]);
}
if(low[x]==dfn[x])
{
z[top+1]=-1;
cnt++;
while(z[top+1]!=x)
{
f[z[top]]=cnt;
w[z[top]]=0;
top--;
}
}
}
bool cmp(node a,node b)
{
return a.x<b.x || (a.x==b.x && a.y<b.y);
}
int main()
{
freopen("rebuild.in","r",stdin);
freopen("rebuild.out","w",stdout);
read(n);read(m);
while(n!=0 && m!=0)
{
tot=1;memset(b,0,sizeof(b));
for(int i=1;i<=m;i++)
read(x),read(y),ins(x,y),ins(y,x);
memset(bz,1,sizeof(bz));
memset(w,0,sizeof(w));
id=cnt=top=0;
tarjan(1,0);
tot=0;memset(b1,0,sizeof(b1));
for(int i=1;i<=n;i++)
for(int j=b[i];j;j=nxt[j])
if(f[i]!=f[to[j]])ins1(f[i],f[to[j]]);
mx=0;memset(bz,1,sizeof(bz));
dfs(1,0);
mx=0;memset(bz,1,sizeof(bz));
dfs(pos,0);
printf("%d\n",cnt-mx-1);
read(n);read(m);
}
return 0;
}