HDU 3394 Railway 块
http://acm.hdu.edu.cn/showproblem.php?pid=3394
求有几个边不在环中,有几个边在不同的环中
代码:
//块没有割点的连通子图
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#define Min(a,b)a<b?a:b
#define nMAX 10002
#define mMAX 20002
using namespace std;
int head[nMAX],dfn[nMAX],low[nMAX],stack[nMAX],num[nMAX];//de_sta[nMAX];//栈中点的个数
int s_edge,n,top,times;
int zero,one,two;
int atype,belon[nMAX];
bool vs[nMAX];
struct
{
int to,next;
}edge[mMAX];
void addedge(int u,int v)
{
s_edge++;
edge[s_edge].to=v;
edge[s_edge].next=head[u];
head[u]=s_edge;
}
void check(int s)
{
int i,j,k=0;
memset(vs,0,sizeof(vs));
for(i=1;i<=s;i++)
vs[num[i]]=1;
for(i=1;i<=s;i++)
{
for(int e=head[num[i]];e;e=edge[e].next)
{
int v=edge[e].to;
if(vs[v])k++;
}
}
k/=2;
if(k==s)one+=k;
else if(k>s)two+=k;
// else zero+=k;
}
void tarjan(int u,int fa)
{
dfn[u]=++times;
low[u]=times;
stack[++top]=u;
int e;
for(e=head[u];e;e=edge[e].next)
{
int v=edge[e].to;
if(v==fa)continue;
if(!dfn[v])
{ cout<<"u,v="<<u<<" "<<v<<endl;
tarjan(v,u);
low[u]=Min(low[u],low[v]);
int j;
int cnt;
if(dfn[u]<=low[v])//u是割点
{
atype++;
cnt=0;
do
{
j=stack[top--]; belon[j]=atype;
num[++cnt]=j;
vs[j]=1;
}while(j!=v);
num[++cnt]=u;//割点属于多个块
belon[u]=atype;
// vs[u]=1;
check(cnt);
}
}
else low[u]=Min(low[u],dfn[v]);//加不加(v!=fa)均可,因为u是割点
}
return ;
}
void init()
{
atype=0;
s_edge=0;
top=0;
times=0;
memset(head,0,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
return ;
}
int main()
{
int m,u,v,i;
while(~scanf("%d%d",&n,&m))
{
if(n==0&&m==0)break;
init();
while(m--)
{
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
zero=one=two=0;
for(i=0;i<n;i++)
if(!dfn[i])
tarjan(i,-1);
zero=s_edge/2-two-one;
// for(i=0;i<n;i++)
// cout<<"low["<<i<<"]="<<low[i]<<endl;
printf("%d %d\n",zero,two);
}
return 0 ;
}

浙公网安备 33010602011771号