http://acm.hdu.edu.cn/showproblem.php?pid=4612
Problem Description 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.
Input The input contains multiple cases.
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 0
Sample Output
0 |
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <functional>
#include <climits>
using namespace std;
#define LL long long
const int INF=0x3f3f3f3f;
const int N=200010;
const int M=1000010;
struct Edge
{
int v,nt,flag;
} edge[M<<2];
int s[N],cnt;
int n,m;
int dfn[N],low[N],dep,vis[N];
int id[N],res;
bool instack[N];
int nbridge,bridge[M][2];
int maxlen;
stack<int>st;
void AddEdge(int u,int v)
{
edge[cnt].v=v;
edge[cnt].nt=s[u];
edge[cnt].flag=1;
s[u]=cnt++;
edge[cnt].v=u;
edge[cnt].nt=s[v];
edge[cnt].flag=1;
s[v]=cnt++;
}
void tarjan(int u,int pre) // 无向图,数据有回边.需要将其看做不同边.且边需要标记...
{
vis[u]=true;
dfn[u]=low[u]=++dep;
st.push(u);
instack[u]=true;
for(int i=s[u]; ~i; i=edge[i].nt)
{
int v=edge[i].v;
if(edge[i].flag==false) continue;
edge[i].flag=edge[i^1].flag=false;
if(!vis[v])
{
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(dfn[u]<low[v])
{
bridge[nbridge][0]=u;
bridge[nbridge++][1]=v;
}
}
else if(instack[v]) low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
int t;
do
{
id[t=st.top()]=res;
st.pop();
instack[t]=false;
}
while(t!=u);
res++;
}
}
int dfs(int u,int pre)
{
int tmp=0;
for(int i=s[u];~i;i=edge[i].nt)
{
int v=edge[i].v;
if(v==pre) continue;
int d=dfs(v,u);
maxlen=max(maxlen,tmp+d);//树的深度;
tmp=max(tmp,d);
}
return tmp+1;
}
int main()
{
while(~scanf("%d%d",&n,&m)&&(n+m))
{
memset(s,-1,sizeof s);
cnt=0;
for(int i=0; i<m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
AddEdge(u,v);
}
memset(vis,0,sizeof vis);
memset(instack,0,sizeof instack);
nbridge=0,res=0,dep=0;
while(!st.empty()) st.pop();
for(int i=1; i<=n; i++)
if(!vis[i]) tarjan(i,0);
memset(s,-1,sizeof s);
cnt=0;
for(int i=0;i<nbridge;i++)
{
int u=id[bridge[i][0]],v=id[bridge[i][1]];
AddEdge(u,v);
}
maxlen=0;
dfs(0,-1);
printf("%d\n",res-1-maxlen);
//printf("%d\n",res);缩点数
//printf("%d\n",maxlen);//树直径
}
return 0;
}