题意:求出割点以及除去割点后的连通分量的数量(附带求出了点双连通分量(块)) [求割点]对图深度优先搜索,定义DFS(u)为u在搜索树(以下简称为树)中被遍历到的次序号。定义Low(u)为u或u的子树中能通过非父子边追溯到的最早的节点,即DFS序号最小的节点。根据定义,则有:Low(u)=Min {DFS(u),DFS(v)|(u,v)为后向边(等价于DFS(v)<DFS(u)且v不为u的父亲节点),Low(v)|(u,v)为树枝边} [条件]一个顶点u是割点,当且仅当满足(1) u为树根,且u有多于一个子树。或(2) u不为树根,且满足存在(u,v)为树枝边(即u为v在搜索树中的父亲),使得DFS(u)<=Low(v)。 [除去点后的连通分量的]:对于(1)的割点,数量为子树的数量;(2)的数量就是满足条件的v的个数+1(它的父亲节点). [求点双连通分支]对于点双连通分支,实际上在求割点的过程中就能顺便把每个点双连通分支求出。建立一个栈,存储当前双连通分支,在搜索图时,每找到一条树枝边或后向边,就把这条边加入栈中。如果遇到某时满足DFS(u)<=Low(v),说明u是一个割点,同时把边从栈顶一个个取出,直到遇到了边(u,v),取出的这些边与其关联的点,组成一个点双连通分支。割点可以属于多个点双连通分支,其余点和每条边只属于且属于一个点双连通分支。


#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MID(x,y) ((x+y)>>1)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;const int MAXE = 1000005;
const int MAXV = 1005;
struct node{int u, v;int next;
}arc[MAXE];
int cnt, head[MAXV];
void init(){cnt = 0;mem(head, -1);
}
void add(int u, int v){arc[cnt].u = u;arc[cnt].v = v;arc[cnt].next = head[u];head[u] = cnt++;arc[cnt].u = v;arc[cnt].v = u;arc[cnt].next = head[v];head[v] = cnt++;return ;
}int id, dfn[MAXV], low[MAXV];       //时间戳
int bcc_num;                        //点双联通分量标号
vector  bcc[MAXV];             //因为割点可以属于多个双联通分量,所以用数组存储每个双联通分量的节点而不是用标号数组表示每个节点所属的双联通分量
stack  st;                     //栈中存着树枝边或后向边
int res[MAXV];                      //本题所求答案,即割点连接的双联通分量个数,树根是子树个数,非树根是子树个数+1.
void addbcc(int bcc_num, int u){for (int i = 0; i < (int)bcc[bcc_num].size(); i ++){if (bcc[bcc_num][i] == u)return ;}bcc[bcc_num].push_back(u);
}
void tarjan(int u, int father){dfn[u] = low[u] = ++id;int child = 0;for (int i = head[u]; i != -1; i = arc[i].next){int v = arc[i].v;if (v == father)    continue;if (dfn[v] < dfn[u]){   //避免正向边st.push(i);if (!dfn[v]){       //树枝边child ++;       //注意这里统计儿子节点时不要写在if外面tarjan(v, u);low[u] = min(low[u], low[v]);if (dfn[u] <= low[v]){bcc_num ++;res[u] ++;              //非树根节点连接的双联通分量个数while(!st.empty()){int su = arc[st.top()].u;int sv = arc[st.top()].v;st.pop();addbcc(bcc_num, su);addbcc(bcc_num, sv);if((su == u && sv == v) || (su == v && sv == u)){break;}}}}else{               //后向边low[u] = min(low[u], dfn[v]);}}}//统计割点连接的双联通分量个数if (father == 0){if (child >= 2){        //树根大于一个子树才是割点res[u] = child;}elseres[u] = 0;}else if (res[u] > 0)        //非树根除了子树个数还要加上父亲节点res[u] ++;
}
void solve(){id = bcc_num = 0;mem(dfn, 0);mem(low, 0);mem(res, 0);while(!st.empty())st.pop();tarjan(1, 0);
}
int main(){int u, v;int t = 0;while(scanf("%d", &u) == 1){init();++ t;if (u == 0)break;if (t > 1)puts("");scanf("%d", &v);add(u, v);while(scanf("%d", &u) == 1){if (u == 0)break;scanf("%d", &v);add(u, v);}solve();bool flag = 0;printf("Network #%d\n", t);for (int i = 1; i <= MAXV; i ++){if (res[i] > 0){printf("  SPF node %d leaves %d subnets\n", i, res[i]);flag = 1;}}if (!flag){puts("  No SPF nodes");}}return 0;
}

转载于:https://www.cnblogs.com/AbandonZHANG/archive/2013/05/30/4114026.html

POJ 1523 SPF (割点 点双连通分量)相关推荐

  1. POJ 1523 SPF 割点与桥的推断算法-Tarjan

    题目链接: POJ1523 题意: 问一个连通的网络中有多少个关节点,这些关节点分别能把网络分成几部分 题解: Tarjan 算法模板题 顺序遍历整个图,能够得到一棵生成树: 树边:可理解为在DFS过 ...

  2. Redundant Paths POJ - 3177(tarjan+边双连通分量)

    题意: 有n个牧场,要求从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新建多少条路,使得任何两个牧场之间至少有两条独立的路.两条独立的路是指:没有公共边的路,但可以经过 ...

  3. poj 3352 Road Construction(边-双连通分量)

    题意:给定一个连通的无向图G,至少要添加几条边,才能使其变为双连通图. 解题思路: 显然,当图G存在桥(割边)的时候,它必定不是双连通的.桥的两个端点必定分别属于图G的两个[边双连通分量](注意不是点 ...

  4. poj 1523 SPF (无向图 的 割点)

    http://poj.org/problem?id=1523 题意:  求  无向图的 个点,以及 将个点 去掉后  图 被分成 几个联通块: 题解:  tarjan   .   1 #include ...

  5. POJ 1523 SPF

    大意:求割顶的数量以及删除割顶之后子图的数量. 思路:Tarjan算法求割顶,同POJ 1144 NetWork. CODE1: #include<cstdio> #include< ...

  6. tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)

    基本概念 给定无向连通图G = (V, E) 割点: 对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点 割边(桥) 若对于e∈E,从图中删去边e之 ...

  7. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)...

    转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2194090a96bbed2db1351de8.html 基本概念: 1.割点:若删掉某点后,原连通图 ...

  8. 学习有向图和无向图的强连通分量(基本概念+割点+点双联通分量+桥+边双连通分量+全套模板【Tarjan】)

    最近总是考到Tarjan,让我措手不及 基本概念 割点以及点双连通分量 Tarjan法求割点 推导过程 代码实现 Tarjan法求点双连通分量 推导过程 代码实现 有向图的Tarjan缩点 桥与边双连 ...

  9. 【POJ - 3352】Road Construction(Tarjan,边双连通分量)

    题干: It's almost summer time, and that means that it's almost summer construction time! This year, th ...

最新文章

  1. R假设检验之Breusch-Pagan检验(Breusch-Pagan Test)
  2. 自然语言处理(四)统计机器翻译SMT
  3. 如何使用schematics快速创建全新的SAP Spartacus Storefront并启用SSR
  4. android handler封装_Handler都没搞懂,你拿什么去跳槽啊?!
  5. centos7限制cpu使用_Centos7 - 使用cgroups限制进程资源
  6. vue2.0 自定义 生成二维码(QRCode)组件
  7. python流程控制几种_python基础流程控制与数据类型
  8. Python编程实例(4)
  9. ArrayList ListItr
  10. Entity Framework连接Mysql数据库并生成Model和DAL层
  11. 无聊的时候去火箭队官网调戏客服
  12. 服务器显示RL011,台达伺服驱动器维修之AL011故障原因和方法
  13. MATLAB2017安装步骤
  14. 各种调制方式OFDM(QPSK,16QAM,64QAM)系统性能仿真
  15. Quora Question Pairs 思路记录
  16. GTK使用cairo绘图教程
  17. 关于WPF的资源引用问题
  18. 性能测试5-性能测试环境搭建
  19. 《C语言程序设计》江宝钏主编-习题6-2-排列数
  20. 建造者模式(Builder Pattern)【创建型】

热门文章

  1. 树莓派基金会来号召用键盘生物学家研究企鹅
  2. DBlink的创建与删除
  3. 小程序类似抖音视频整屏切换
  4. 挑战程序设计竞赛 (秋叶拓哉 / 岩田阳一 / 北川宜稔 著)
  5. cas单点登录-jdbc认证(三)
  6. centos 7.0上RabbitMQ 3.5.6版本多实例启动操作讲解
  7. 统一项目管理平台(UMPlatForm.NET)-4.7 组织机构管理模块
  8. 时隔一年俺又回来了..
  9. 嵌入式软件开发工程师谈软件架构的设计
  10. 持续集成coding