• POJ1523 Tarjan求割点以及删除割点之后强连通分量的数量


    题目链接:http://poj.org/problem?id=1523

    SPF:A Single Point of Failure也就是割点(一个点导致网络之间的不连通),由于给出的图是无向图,所以只要连通就一定强连通。要求连通分支的数量就是要求请联通分支的数量,我们可想到tarjan求强连通的步骤,只要一群结点的low值相同他们就是属于同一个SCC(Strongly Connected Component),所以我们只要对于每一个割点,记录一下这个点所到的其他结点的不相同的low值的数量,就是这个点能够将网络分成的连通分支的数量。因为在dfs树上,如果一个根结点是割点的话,对于他的每一个子节点,我们进行一次深搜(没访问过的),并且标记访问,表上记号,等到所有的子结点全部搜完就记号的数量就是强连通分量的个数。

    代码如下:

     1 #include<cstdio>
     2 #include<string.h>
     3 #include<set>
     4 #include<iostream>
     5 using namespace std;
     6 const int  maxn =1e3+10;
     7 int head[maxn],nxt[maxn],iscut[maxn],dfn[maxn],low[maxn];
     8 bool vis[maxn];
     9 struct node{
    10     int u,v;
    11 }p[maxn];
    12 int e;
    13 int n,cnt;
    14 void addedge(int u,int v)
    15 {
    16     p[e].u=u;
    17     p[e].v=v;
    18     nxt[e]=head[u];
    19     head[u]=e++;
    20  } 
    21 void tarjan(int u,int fa)
    22 {
    23     dfn[u]=low[u]=++cnt;//dfn为dfs时间戳,low为回退边指向的最小祖先 
    24     int child=0;
    25     for(int i=head[u];~i;i=nxt[i])
    26     {
    27         int v=p[i].v;
    28         if(!dfn[v])
    29         {
    30             tarjan(v,u);
    31             low[u]=min(low[u],low[v]);
    32             child++;
    33             if(u!=1&&low[v]>=dfn[u])iscut[u]=1;
    34         }
    35         else if(dfn[v]<dfn[u]&&v!=fa)//回退边 
    36         {
    37             low[u]=min(low[u],dfn[v]);
    38         }
    39     }
    40     if(u==1&&child>=2)iscut[1]=1;
    41 } 
    42 int main()
    43 {
    44     int x,y;
    45     int step=0;
    46     while(scanf("%d",&x)&&x)
    47     {
    48         scanf("%d",&y);
    49         n=0;
    50         memset(head,-1,sizeof(head));
    51         memset(nxt,-1,sizeof(nxt));
    52         memset(dfn,0,sizeof(dfn));
    53         memset(low,0,sizeof(low));
    54         memset(iscut,0,sizeof(iscut));
    55         memset(vis,0,sizeof(vis));
    56         cnt=0;
    57         e=0;
    58         n=max(max(x,y),n);
    59         addedge(x,y);addedge(y,x);
    60         while(scanf("%d",&x)&&x)
    61         {
    62             scanf("%d",&y);
    63             n=max(max(x,y),n);
    64             addedge(x,y);addedge(y,x);
    65         }
    66         tarjan(1,-1);//从结点一开始建立dfs树 
    67         set<int> s;
    68         bool flag=false;
    69         printf("Network #%d
    ",++step);
    70         for(int i=1;i<=n;i++)
    71         {
    72             s.clear();
    73             if(iscut[i])//对于每一个割点查找连通分量的数量 
    74             {
    75                 flag=true;
    76                 for(int j=head[i];~j;j=nxt[j])
    77                 {
    78                     s.insert(low[p[j].v]);//搜索不同的low值数量
    79                 }
    80             }
    81             if(s.size())
    82             printf("  SPF node %d leaves %d subnets
    ",i,s.size()); 
    83         }
    84         if(!flag)printf("  No SPF nodes
    ");
    85         printf("
    ");
    86     }
    87 }
  • 相关阅读:
    C# : WebRequest发起Http Post请求模拟登陆并cookie处理示例
    ASP.NET 缓存数据添加的六种方法。(Insert 与add 的区别)
    SQL Server 2005和SQL Server 2000数据的相互导入
    Web:缓存全解析
    Juqery : 漂亮实用的商品图片jquery tips提示框(无图片箭头+阴影)
    SQL:存储C#中DateTime类型Ticks的值
    Sql Server2005 TransactSQL 排名函数
    Asp.Net :CheckBoxList用法
    jquery.Ajax() 方法调用Asp.Net 后台方法
    ASP.NET: 缓存运用
  • 原文地址:https://www.cnblogs.com/randy-lo/p/12582881.html
Copyright © 2020-2023  润新知