题目大意:求无向图的割点.
无向图割点求法:DFS搜索生成树中,如果一个节点的一颗子树的所有节点都不存在到该节点
的祖先的回边,那么该节点为割点。
建立两个数组,dfn[ ], low[ ].dfn[i]代表搜索的次序,low[i]代表该节点(或者该节点所有子孙)通
过回边到达i的祖先的最小次序(该祖先的dfn),初始化low[i]=dfn[i] (low[i]起码会被置成dfn[w],w为i的父亲)
当有low[u]>=dfn[i](u是i的儿女)时,i为割点.
#include<iostream>
#include<string>
#include<cstring>
using namespace std;
class Edge
{
public:
int v;
Edge *next;
Edge(int _v=0,Edge *_next=NULL):v(_v),next(_next){}
};
class SPF
{
Edge *edge[1009];
Edge toUse[1001*1000];
int dfn[1009],low[1009],subnets[1009];//subnets[i]:i点去掉之后,原图将分为subnets[i]个连通分量;
bool visited[1009];
int haveUsed,depth;
void initial(int,int);
void dfs(int);
public:
void work(int,int);
};
//初始化图
void SPF::initial(int u,int v)
{
memset(edge,NULL,sizeof(edge));
memset(visited,false,sizeof(visited));
for(int i=1;i<=1000;i++)
subnets[i]=1;
haveUsed=0;
depth=1;
while(true)
{
Edge *p=&toUse[haveUsed++];
p->next=edge[u];
p->v=v;
edge[u]=p;
p=&toUse[haveUsed++];
p->next=edge[v];
p->v=u;
edge[v]=p;
cin>>u;
if(u==0)break;
cin>>v;
}
}
void SPF::work(int u,int v)
{
initial(u,v);
dfs(u);
int i;
bool f=false;
for(i=1;i<=1000;i++)
{
if(visited[i]&&subnets[i]>1)
{
cout<<" SPF node "<<i<<" leaves "<<subnets[i]<<" subnets"<<endl;
f=true;
}
}
if(!f)cout<<" No SPF nodes"<<endl;
}
void SPF::dfs(int u)
{
dfn[u]=depth++;
low[u]=dfn[u];//第一种取值
visited[u]=true;
Edge *p=edge[u];
while(p)
{
if(visited[p->v]==true)
low[u]=min(low[u],dfn[p->v]);//第二种取值
else
{
dfs(p->v);
low[u]=min(low[u],low[p->v]);//第三种取值
if(low[p->v]>=dfn[u])
subnets[u]++;
}
p=p->next;
}
if(dfn[u]==1)subnets[u]--;//树的根的特性
}
SPF S;
int main()
{
int u,v,i=0;
while(true)
{
i++;
cin>>u;
if(u==0)break;
cin>>v;
cout<<"Network #"<<i<<endl;
S.work(u,v);
cout<<endl;
}
return 0;
}