// Note:Your choice is C++ IDE
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define min(a,b) ((a)>(b)?(b):(a))
typedef struct sldfj
{
int u;
int v;
int next;
}Edge;
const int mmax=10050;
Edge edge[mmax*20];
int dfsnum[mmax],low[mmax],Time,Enum,root,n,m,head[mmax],top;
int stack[mmax*100];
int ans1,ans2;
bool vis[mmax];
void add(int u,int v)
{
edge[Enum].u=u;
edge[Enum].v=v;
edge[Enum].next=head[u];
head[u]=Enum++;
}
void insert(int u,int v)
{
add(u,v);
add(v,u);
}
void dfs(int u,int fa)
{
dfsnum[u]=low[u]=++Time;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v!=fa&&dfsnum[v]<dfsnum[u])
{
stack[top++]=i;
if(dfsnum[v]<0)
{
dfs(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfsnum[u])//割点
{
int dnum=0,bnum=0,e,s,t;
memset(vis,0,sizeof(vis));
do{//下面退出来的边和点是一个双连通分量
e=stack[--top];
s=edge[e].u;
t=edge[e].v;
bnum++;
if(!vis[s])
{
dnum++;
vis[s]=1;
}
if(!vis[t])
{
dnum++;
vis[t]=1;
}
}while(e!=i);
if(dnum<bnum)
ans2+=bnum;
}
if(low[v]>dfsnum[u])//桥
ans1++;
}
else low[u]=min(low[u],dfsnum[v]);
}
}
}
int main()
{
while(scanf("%d%d",&n,&m))
{
int i;
if(!n&&!m)break;
Enum=0;
memset(head,-1,sizeof(head));
for(i=0;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
insert(a,b);
}
Time=0;
top=0;
ans1=ans2=0;
memset(dfsnum,-1,sizeof(dfsnum));
for(i=0;i<n;i++)
if(dfsnum[i]<0)dfs(i,-1);
printf("%d %d\n",ans1,ans2);
}
return 0;
}
CDOJ1208 作为求双连通分量的模板
最新推荐文章于 2025-08-13 19:57:41 发布