http://poj.org/problem?id=1523
题意:给你一个有N个点的network,要你求图中的割点,对应每个割点给出删除该割点之后,图会变成几个不连通的子图。
思路:双连通求割点,对于第二问,其实只需要求出割点在哪几个双连通子图中出现过即可。
代码:
#include<stdio.h>
#include<string.h>
const int MAXN = 1010 ;
int g[MAXN][MAXN],N;
bool vis[MAXN] ;
int dfn[MAXN] , low[MAXN] , stack[MAXN] ;
int top , idx , cnt ;
int bcc[MAXN][MAXN] ;
void init(){
for(int i=1;i<MAXN;i++)
for(int j=1;j<MAXN;j++)
g[i][j] = 0 ;
memset(vis , 0 ,sizeof(vis));
}
void tarjin(int x, int pre){
dfn[x] = low[x] = ++idx ;
stack[++top] = x ;
for(int i=1;i<MAXN;i++){
if(i==pre || g[x][i]==0 || vis[i]==0) continue ;
if( dfn[i]==-1 ){
tarjin(i,x) ;
if( low[i] < low[x])
low[x] = low[i] ;
if( low[i] >= dfn[x] ){
++ cnt ;
int u ;
do{
u = stack[top--] ;
bcc[cnt][u] = 1 ;
}while( u!=i ) ;
bcc[cnt][x] = 1 ;
}
}
else if( dfn[i]<low[x])
low[x] = dfn[i] ;
}
}
void solve(){
idx = top = cnt = 0 ;
memset(dfn, -1, sizeof(dfn));
memset(bcc , 0 , sizeof(bcc));
for(int i=1;i<MAXN;i++){
if( vis[i] == 0) continue ;
if( dfn[i] == -1){
tarjin(i , -1);
}
}
bool f = 1 ;
for(int i=1;i<MAXN;i++){
if( vis[i]==0 ) continue ;
int c = 0 ;
for(int j=1;j<=cnt;j++){
if( bcc[j][i] == 1) c++ ;
}
if(c == 1) continue ;
f = 0 ;
printf(" SPF node %d leaves %d subnets\n",i,c);
}
if(f){
printf(" No SPF nodes\n");
}
printf("\n");
}
int main(){
int a, b , cas;
cas = 0 ;
while(true ){
scanf("%d",&a);
if(a == 0) break ;
++cas ;
init() ;
vis[a] = 1 ;
scanf("%d",&b);
vis[b] = 1 ;
g[a][b] = g[b][a] = 1 ;
while(1){
scanf("%d",&a);
if(a == 0) break ;
scanf("%d",&b);
g[a][b] = g[b][a] = 1 ;
vis[a] = vis[b] = 1 ;
}
printf("Network #%d\n",cas);
solve() ;
}
return 0 ;
}