题目大意:给一个无自环无重边的图。如果一条边不在任何简单环上,是一类边;如果一条边在两个或以上简单环上,是另一类边。求图中这两类的边的个数。
思路:第一类边即是桥,关键是第二类边怎么求。在一个点-双连通集团中,边的个数>点的个数,那么每条边都在至少两个环上。
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<map>
#include<set>
using namespace std;
#define MP(x,y) make_pair((x),(y))
#define PB(x) push_back(x)
typedef __int64 LL;
//typedef unsigned __int64 ULL;
/* ****************** */
const int INF=100011122;
const double INFF=1e100;
const double eps=1e-8;
const int mod=9999991;
const int NN=10005;
const int MM=100010*2;
/* ****************** */
struct G
{
int u,v,next;
}E[MM];
int p[NN],T;
int dfn[NN],low[NN],tsp;
int sta[MM],sta_top;
int id[NN],id_cnt;
int qiao,ans;
void add(int u,int v)
{
E[T].u=u;
E[T].v=v;
E[T].next=p[u];
p[u]=T++;
}
void bcc(int u,int fa)
{
int i,v;
int dian,bian,ii;
dfn[u]=low[u]=++tsp;
for(i=p[u];i+1;i=E[i].next)
{
v=E[i].v;
if(dfn[v]==0)
{
sta[++sta_top]=i;
bcc(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u])
qiao++;
if(low[v]>=dfn[u])
{
dian=0;
bian=0;
id_cnt++;
for(;;)
{
ii=sta[sta_top--];
bian++;
if(id[E[ii].u]!=id_cnt)
{
id[E[ii].u]=id_cnt;
dian++;
}
if(id[E[ii].v]!=id_cnt)
{
id[E[ii].v]=id_cnt;
dian++;
}
if(E[ii].u==u && E[ii].v==v)
break;
}
if(bian>dian)
ans+=bian;
}
}
else if(dfn[v]<dfn[u] && v!=fa)
{
sta[++sta_top]=i;
low[u]=min(low[u],dfn[v]);
}
}
}
int main()
{
int n,m;
int u,v,i;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0 && m==0)
break;
memset(p,-1,sizeof(p));
T=0;
while(m--)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
tsp=0;
sta_top=0;
id_cnt=0;
for(i=0;i<n;i++)
{
dfn[i]=low[i]=0;
id[i]=-1;
}
qiao=ans=0;
for(i=0;i<n;i++)
{
if(dfn[i]==0)
bcc(i,-1);
}
printf("%d %d\n",qiao,ans);
}
return 0;
}