之前一直没有遇到类似的题,前些天写连通图的时候真是被打了个措手不及,所以下面这个题虽然主要是通过tarjan缩点来求解的,但是前面关于tarjan算法的记录已经完成了,而且求树的直径感觉挺重要的,所以就在这里介绍一下,代码中关于求树的直径的代码很精辟啊,一次深搜完成,是我复制别人的····我自己肯定写不出来这样的代码,难受啊
树的直径通过两次搜索实现(深搜广搜都可以),第一次找出深度最大的节点,第二次以该节点为根再次搜索,再次找到的最大的深度就是树的直径,很简单,实现也不难·····但是要我想的话大概要花一些时间
N planets are connected by M bidirectional channels that allow instant transportation. It's always possible to travel between any two planets through these channels.
If we can isolate some planets from others by breaking only one channel , the channel is called a bridge of the transportation system.
People don't like to be isolated. So they ask what's the minimal number of bridges they can have if they decide to build a new channel.
Note that there could be more than one channel between two planets.
Input The input contains multiple cases.
If we can isolate some planets from others by breaking only one channel , the channel is called a bridge of the transportation system.
People don't like to be isolated. So they ask what's the minimal number of bridges they can have if they decide to build a new channel.
Note that there could be more than one channel between two planets.
Each case starts with two positive integers N and M , indicating the number of planets and the number of channels.
(2<=N<=200000, 1<=M<=1000000)
Next M lines each contains two positive integers A and B, indicating a channel between planet A and B in the system. Planets are numbered by 1..N.
A line with two integers '0' terminates the input.Output For each case, output the minimal number of bridges after building a new channel in a line.Sample Input
4 4 1 2 1 3 1 4 2 3 0 0Sample Output
0
题目大意:有一些星球被一些通道连接着,但是这些通道里面存在一些桥,现在可以新建一个通道,求建一个通道后还剩下的最小桥的个数
题解:对连通分量进行缩点,然后求缩点后的树的直径即可
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define Maxn 200005
#define Maxm 2000005
int dfn[Maxn],low[Maxn];
int cnt[Maxn],du[Maxn];
int jvl[Maxn];
int vis[Maxn];
int head[Maxn];
int u[Maxm];
int v[Maxm];
int _next[Maxm];
int c,num,nu,re;
int sta[Maxn];
int top;
int Max,p;
void into(){
memset(head,-1,sizeof(head));
memset(cnt,0,sizeof(cnt));
memset(dfn,0,sizeof(dfn));
memset(du,0,sizeof(du));
memset(vis,0,sizeof(vis));
c=0;
num=0;
nu=0;
re=0;
top=0;
Max=0;p=0;
}
void add(int s,int t){
u[c]=s;
v[c]=t;
_next[c]=head[s];
head[s]=c++;
}
void dfs(int k,int fa){
dfn[k]=low[k]=++num;
sta[top++]=k;
int flag=0;
for(int i=head[k];i!=-1;i=_next[i]){
int e=v[i];
if(!dfn[e]){
dfs(e,k);
low[k]=min(low[k],low[e]);
}
else if(e==fa&&!flag){
flag=1;
continue;
}
else low[k]=min(low[k],dfn[e]);
}
if(dfn[k]==low[k]){
if(fa!=-1) re++;
++nu;
int a;
do{
a=sta[--top];
cnt[a]=nu;
}while(a!=k);
}
}
int dfss(int k,int pre)
{
int tmp=0;
for(int i=head[k];i!=-1;i=_next[i])
{
int e=v[i];
if(e==pre||e==k) continue;
int d=dfss(e,k);
Max=max(Max,tmp+d);
tmp=max(tmp,d);
}
return tmp+1;
}
void rec(int i){
u[i]=cnt[u[i]];
v[i]=cnt[v[i]];
_next[i]=head[u[i]];
head[u[i]]=i;
}
int main(){
int n,m;
while(scanf("%d%d",&n,&m)){
if(n==0&&m==0) break;
into();
for(int i=0;i<m;i++){
int s,t;
scanf("%d%d",&s,&t);
add(s,t);
add(t,s);
}
for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i,-1);
memset(head,-1,sizeof(head));
for(int i=0;i<c;i++) rec(i);
Max=0;
dfss(1,-1);
// printf("%d %d\n",re,Max);
printf("%d\n",re-Max);
}
}