题意:给出一个网络(不一定连通),求所有的割点,以及割点可以切分出多少个连通分量。

思路:很多种情况。

(1)如果给的图已经不是连通图,直接“  No SPF nodes”。

(2)求所有割点应该不难,就是tarjan发明的算法搞定。但是求连通分量就得小心了,多种情况。看下:

  1)如果一个割点x,其所有孩子都不是割点,那么x至少可以割出两个连通分量(x之上和之下的各1个)。

  2)如果一个割点x,其有部分孩子是割点,有部分孩子并不是割点,那么x可以割出x之上的1个连通分量,不是割点的孩子均是同1个连通分量,是割点的孩子各自分别是一个连通分量。

  3)如果一个割点x,如果有些孩子是叶子节点,且该叶子节点的度为1,即连着x,那么该叶子节点会被割出来,单点也是连通分量。

 //#include <bits/stdc++.h>
#include <iostream>
#include <cmath>
#include <cstdio>
#include <vector>
#include <cstring>
#include <climits>
using namespace std;
const int N=;
int mapp[N][N];
int cntr, flag, up; //时间戳
int dfn[N], low[N], vis[N], iscut[N], cur[N]; //记录时间戳, 反边最顶点, 访问记录, 是否连通分量 bool DFS(int x, int far)
{
int chd=; //孩子节点个数
int cnt=, sum=;
dfn[x]=low[x]=++cntr; //时间戳
vis[x]=; //DFS必备
for(int i=; i<=up; i++)
{
if(!mapp[i][x]) continue;
if(!vis[i]) //树边
{
chd++;
bool f=DFS(i,x); //i点只有一条边
low[x]=min(low[x],low[i]); //判断连通分量的个数
if(!far && chd> || far && low[i]>=dfn[x] ) //能让x成为割点的孩子i
{ sum++;
iscut[x]=;
if(iscut[i]||f) cnt++; //这个孩子是割点或者满足单点单边条件
}
}
else if(i!=far)
low[x]=min(low[x], dfn[i]);
}
if(!far && iscut[x])
{
iscut[x]=cnt; //根节点
if(sum>cnt) iscut[x]++;
}
if( far && iscut[x]) //非根节点
{
if(!cnt ) iscut[x]=; //没有“是割点”的孩子,那么只要自己是割点,起码可以割为两个连通分量
else if(sum==cnt) iscut[x]=cnt+; //有“是割点”的孩子,那么每个“割点”孩子是1个连通分量,注:有可能还有非割点孩,他们算1个连通分量
else iscut[x]=cnt+;
}
if(iscut[x]) flag=; //无割点的标记'
//if(x==1) cout<<"**"<<sum<<endl; if(!chd && low[x]==dfn[x] ) return true; //返回值用于判断是否是叶子,且没有反向边到fa之上
return false;
} void cal() //n为边数
{ flag=cntr=;
DFS(up,); //深搜求割点数
int i;
for(i=; i<=up; i++) //先确保是个连通图
if(cur[i]&&!vis[i])
{
printf(" No SPF nodes\n");
return ;
} for(i=; i<=up; i++)
if(cur[i]&&iscut[i])
{
printf(" SPF node %d leaves %d subnets\n", i, iscut[i]);
} if(!flag) printf(" No SPF nodes\n");
}
void init()
{
up=;
memset(cur,,sizeof(cur));
memset(mapp,,sizeof(mapp));
memset(vis,,sizeof(vis));
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(iscut,,sizeof(iscut)); } int main()
{
freopen("input.txt", "r", stdin);
int j=, a, b;
while()
{
int cnt=;
init();
while(~scanf("%d",&a))
{
if(!a && !cnt) return ; //没边,a又为0,则结束了
if(!a)
{
printf("Network #%d\n",++j);
cal();
printf("\n");break;
}
scanf("%d",&b);
up=max(max(up,a),b); //记录顶点号上限
cur[a]=cur[b]=; //记录出现的顶点号
mapp[a][b]=mapp[b][a]=; //矩阵
cnt++; //边数
}
}
return ;
}

AC代码

POJ 1523 SPF (割点,连通分量)的更多相关文章

  1. poj 1523 SPF(双连通分量割点模板)

    题目链接:http://poj.org/problem?id=1523 题意:给出无向图的若干条边,求割点以及各个删掉其中一个割点后将图分为几块. 题目分析:割点用tarjan算法求出来,对于每个割点 ...

  2. POJ 1523 SPF 割点 Tarjan

    SPF Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 9317   Accepted: 4218 Description C ...

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

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

  4. Electricity POJ - 2117 + SPF POJ - 1523 去除割点后求强连通分量个数问题

    Electricity POJ - 2117 题目描述 Blackouts and Dark Nights (also known as ACM++) is a company that provid ...

  5. zoj 1119 / poj 1523 SPF (典型例题 求割点 Tarjan 算法)

    poj : http://poj.org/problem?id=1523 如果无向图中一个点 u 为割点 则u 或者是具有两个及以上子女的深度优先生成树的根,或者虽然不是一个根,但是它有一个子女 w, ...

  6. POJ 1523 SPF tarjan求割点

                                                                   SPF Time Limit: 1000MS   Memory Limit ...

  7. POJ 1523 SPF(求割点)

    题目链接 题意 : 找出图中所有的割点,然后输出删掉他们之后还剩多少个连通分量. 思路 : v与u邻接,要么v是u的孩子,要么u是v的祖先,(u,v)构成一条回边. //poj1523 #includ ...

  8. POJ 1523 SPF (无向图割点)

    <题目链接> 题目大意: 给你一个连通的无向图,问你其中割点的编号,并且输出删除该割点后,原图会被分成几个连通分量. 解题分析: Tarjan求割点模板题. #include <cs ...

  9. poj 1523 SPF(tarjan求割点)

    本文出自   http://blog.csdn.net/shuangde800 ------------------------------------------------------------ ...

随机推荐

  1. Unity3D 相关项目代码

    一.Application.PresistentDataPath 注意最后面是没有/的 public static string PresistentDataPathForEditor = " ...

  2. Unity3D研究院之打开Activity与调用JAVA代码传递参数

    原地址:http://www.xuanyusong.com/archives/667    Unity for Android 比较特殊,Unity for IOS 打包是将XCODE工程直接交给开发 ...

  3. 【设计模式六大原则4】接口隔离原则(Interface Segregation Principle)

      定义:客户端不应该依赖它不需要的接口:一个类对另一个类的依赖应该建立在最小的接口上. 问题由来:类A通过接口I依赖类B,类C通过接口I依赖类D,如果接口I对于类A和类B来说不是最小接口,则类B和类 ...

  4. JS 变量或参数是否有值的判断

    var node; …… 判断 node 是否有值,是否为 undefine,是否 null,直接使用两个!!,否定之否定: if (!!node){ .... }else{ .... } 这个条件判 ...

  5. 创建和编辑 crontab 文件

    http://docs.oracle.com/cd/E24847_01/html/819-6951/sysrescron-24589.html 创建和编辑 crontab 文件 创建 crontab  ...

  6. lintcode:四个数之和

    题目 四数之和 给一个包含n个数的整数数组S,在S中找到所有使得和为给定整数target的四元组(a, b, c, d). 样例 例如,对于给定的整数数组S=. 满足要求的四元组集合为: (-1, 0 ...

  7. *[hackerrank]Cut the tree

    https://www.hackerrank.com/contests/w2/challenges/cut-the-tree 树分成两部分,求两部分差最小.一开始想多了,后来其实求一下总和,求一下分部 ...

  8. 【mongoDB中级篇②】索引与expain

    索引的操作 数据库百分之八十的工作基本上都是查询,而索引能帮我们更快的查询到想要的数据.但是其降低了数据的写入速度,所以要权衡常用的查询字段,不必在太多字段上建立索引. 在mongoDB中默认是用bt ...

  9. 利用Nginx搭建http和rtmp协议的流媒体服务器

    http://www.linuxidc.com/Linux/2013-02/79118.htm

  10. 使用CAShapeLayer与UIBezierPath画出想要的图形

    使用CAShapeLayer与UIBezierPath可以实现不在view的drawRect方法中就画出一些想要的图形 步骤: 1.新建UIBezierPath对象bezierPath 2.新建CAS ...