POJ1523-SPF

题目链接:http://poj.org/problem?id=1523
题意解析:给出图关系,在图中找关节点,且每个关节点的连通分支
题意分析:赤裸裸的Tarjan算法、、、

代码如下:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#define MAX 1010
#define max(a,b) ( a>b ? a:b )
#define min(a,b) ( a>b ? b:a )

intmap[MAX][MAX]; 
    //邻接矩阵
int vis[MAX]; 
    //标记顶点状态
int dfn[MAX]; 
  //每个顶点的深度优先数
intlow[MAX]; 
      //是从一个点或者它的子孙出发可以到达的最低深度优先数
int sub[MAX]; 
    //记录每个顶点去掉后的连通分量个数
int nodes, son, cnt; 
  //nodes顶点个数,son根结点的子女结点个数,cnt当前搜索的深度优先数
int flag, ncase; 
  //flag标记是否输出,ncase输出的第几组数据

//深度优先搜索,记录每个结点的low值
void DFS( int u ){
 
    int i;
 
    for( i=1;i<=nodes; i++ ){
 
            if( map[u][i]){        //u和i相关,在生成树中有两种情况
 
                    if( !vis[i] ){
 
                            vis[i] = 1;      //i是u的儿子结点
 
                            cnt ++;
 
                            dfn[i] = low[i] = cnt;
 
                            DFS( i );
 
                            low[u] = min( low[u],low[i] );    //回溯时,计算结点u的low值
 
                            if( low[i] >= dfn[u] ){
 
                                    if( u != 1)            //去掉该结点后的连通分量的个数
 
                                            sub[u] ++;
 
                                    if( u == 1)        //根结点的子女结点个数大于2,则根结点是关节点
 
                                            son ++;
 
                            }
 
                    }
 
                    else       //i是u的祖先结点,(u,i)是一条回边
 
                            low[u] = min( low[u], dfn[i] );
 
            }
 
    }
}

//初始化函数
void InitDFS(){
 
    low[1] =dfn[1] = 1;
 
    cnt =1;
 
    son =0;
 
    memset( vis,0, sizeof(vis) );
 
    memset( sub,0, sizeof(sub) );
 
    vis[1] =1;
}

//输出函数
void OutPut(){
 
    int i;
 
    intfind=0;
 
    if( flag ==1 )
 
            printf( "\n" );
 
    printf("Network #%d\n",ncase++ );
 
    flag =1;
 
    if( son> 1 ){
 
            sub[1] = son - 1;
 
    }
 
    for( i=1;i<nodes; i++ ){
 
            if( sub[i] ){
 
                    find = 1;
 
                    printf( "  SPF node %d leaves %d subnets\n", i,sub[i]+1 );
 
            }
 
    }
 
    if( !find)
 
            printf( "  No SPF nodes\n" );
}

int main(){
 
    intu,v;
 
    ncase =1;
 
    nodes =0;
 
    flag =0;
 
    memset( map,0 ,sizeof(map) );
 
    while(scanf( "%d",&u )==1 ){
 
            if( u == 0 ){
 
                    InitDFS();
 
                    DFS( 1 );
 
                    OutPut();
 
                    memset( map, 0 ,sizeof(map) );
 
                    nodes = 0;
 
                    scanf( "%d",&u );
 
                    if( u == 0 )
 
                            return 0;
 
            }
 
            scanf( "%d",&v );
 
            nodes = max( nodes,max( u,v ) );
 
            map[u][v] = map[v][u] = 1;
 
    }
 
    return0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值