作业
2016-07-19 20:45
211 查看
tarjan算法 无向图
割点
如果在连通图G中去掉一个顶点(自然同时去掉与该顶点相关联的所有边)后,该图的连通分支数增加,则称该顶点为G的割点割边
使连通图G的边e不在G的任何一个圈上割点集合
在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合割边集合
如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为割边集合点连通度
最小割点集合中的顶点数边连通度
最小割边集合中的边数~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~
割点
tarjan DFS 对DFS树树根进行判断,是否>1,对于其他的点u,如果非树根的直接son,而且low[u]>=dfn[p[u]],则该点的father v=p[u]使割点。
割边
1,无重边情况,遍历发现T边(u,v)并low[v]>=dfn[u],则(u,v)是割边
2,有重边情况,标记,不能用dfn[u]更新low[v];
例题
POJ的= =!次元地狱门(其实很简单)输入
输入会包括若干网络的描述。一个网络描述会包括若干对的整数,每行一对整数来描述节点的连接情况,先后顺序是无关的,如:1 2和2 1描述了相同的连接。所有的节点编码会从1到1000.一个单独的0行来结束连接节点的列表。一个空的网络描述结束输入。输入文档中空白的行要被忽略。
输出
对于每个输入的网络中,你需要输出存在的SPF节点的列表在文档中。
文档中第一个网络需要用“Network #1”来定义,第二个则是” Network #2”等等(如样例)。每个SPF节点,输出一行,方式如下方例子所示,列出节点的编号和当这个节点失效时完全连通的子网络的个数。如果网络中没有SPF节点,输出“NO SPF nodes“即可。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这题的难点其实并不是无向图系列,而是输入方式= =,其他的只要套模板就能过= =
输入用while(),就像这样:
int t=9999; while(t!=0){ int i=0; P++; for(i=0;i<2;i++){ scanf("%d",&m); if(m==0){ t=0; break; } if(i==0){ n=m; } } addedge(n,m);
其实可以更简单= =,不过我不说~
完整代码如下
#include<stdio.h> #include<string.h> struct node{ int to; int next; } p[1005*1005]; int dfn[1005],low[1005]; int vis[1005]; int cut[1005],head[1005]; int n,e,idex; int root,root_son; int max(int a,int b){ return a<b?b:a; } void add(int u,int v){ p[e].to=v; p[e].next=head[u]; head[u]=e++; } void findCut(int u){ dfn[u]=low[u]=idex++; for(int i=head[u]; i!=-1; i=p[i].next){ int v=p[i].to; if(!dfn[v]){ findCut(v); if(u==root) root_son++; else{ if(low[v]<low[u]) low[u]=low[v]; if(low[v]>=dfn[u]) cut[u]=1; } } else if(low[u]>dfn[v]) low[u]=dfn[v]; } } void dfs(int s){ vis[s]=1; for(int i=head[s]; i!=-1; i=p[i].next){ int v=p[i].to; if(!vis[v]){ vis[v]=1; dfs(v); } } } int main(){ int u,v,t=0; while(scanf("%d",&u)&&u){ t++; n=-1; e=0; idex=1; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(vis,0,sizeof(vis)); memset(cut,0,sizeof(cut)); memset(head,-1,sizeof(head)); n=max(n,u); scanf("%d",&v); n=max(n,v); add(u,v); add(v,u); while(scanf("%d",&u)&&u){ n=max(n,u); scanf("%d",&v); n=max(n,v); add(u,v); add(v,u); } root=1; int flag=0; root_son=0; findCut(root); if(root_son>1) cut[root]=1; printf("Network #%d\n",t); for(int i=1; i<=n; i++){ if(cut[i]){ flag=1; memset(vis,0,sizeof(vis)); vis[i]=1; int son=0; for(int j=head[i]; j!=-1; j=p[j].next){ if(!vis[p[j].to]) { dfs(p[j].to); son++; } } printf(" SPF node %d leaves %d subnets\n",i,son); } } if(!flag) printf(" No SPF nodes\n"); printf("\n"); } return 0; }
坑爹的文本编辑啊,输了好久的都不见了,就剩这破代码了。。哎。。
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- C#递归算法之分而治之策略
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#算法之大牛生小牛的问题高效解决方法
- C#算法函数:获取一个字符串中的最大长度的数字
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法