题意:一个无向图,要找出这个图的割点,判断每个割点去掉之后可以形成多少个双连通分量。
#include<stack>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 1005
#define min(a,b) (a)<(b) ? a:b
#define man(a,b) (a)>(b) ? a:b
struct node{
int u;
int next;
};
node a[maxn];
int DFN[maxn],low[maxn],head[maxn],num[maxn];
int st,en,ti,ret;
void add(int u,int v)
{
a[ti].u=v;
a[ti].next=head[u];
head[u]=ti;
ti++;
}
void tarjan(int s,int t)
{
DFN[t]=low[t]=++ret;
int k;
int son=0;
for(int i=head[t];i;i=a[i].next)
{
k=a[i].u;
if(k!=s&&DFN[k])
low[t]=min(low[t],DFN[k]);
else if(!DFN[k])
{
son++;
tarjan(t,k);
if(low[k]<low[t])
low[t]=low[k];
if((t==st&&son>=2)||(t!=st&&DFN[t]<=low[k]))
num[t]++;
}
}
}
int main()
{
int a,b,count=1;
while(cin>>a,a)
{
cin>>b;
memset(head,0,sizeof(head));
ti=1;ret=0;
st=1005,en=0;
st=min(st,a);
st=min(st,b);
en=max(en,a);
en=max(en,b);
add(a,b);
add(b,a);
while(cin>>a,a)
{
cin>>b;
st=min(st,a);
st=min(st,b);
en=max(en,a);
en=max(en,b);
add(a,b);
add(b,a);
}
memset(DFN,0,sizeof(DFN));
memset(low,0,sizeof(low));
memset(num,0,sizeof(num));
tarjan(0,st);
cout<<"Network #"<<count++<<endl;
bool flag=false;
for(int i=st;i<=en;i++)
if(num[i])
{
flag=true;
cout<<" SPF node "<<i<<" leaves "<<num[i]+1<<" subnets"<<endl;
}
if(!flag)
cout<<" No SPF nodes"<<endl;
cout<<endl;
}
}