sth. about tarjan
2016-09-01 21:11
190 查看
感觉进入了 一个 深坑!
脑子不好使 决定 写一写。。
主要决定 写一写双联通分量
先介绍:
1.割点: 如果一个点去掉 图就不再联通 则这个点 为 割点
2.点双联通: 没有 割点 的图
3.边双连通:没有 割边 的图
那 总结一下 所有 的 tajan吧
1.强连通分量:
2.边双【边双和强连通分量差不了多少 】
3.割点
割点 主要就是:low[f]>=dfn[v];
如果就是根节点 那么 根节点 的子树 大于1
别的点的话 这样 的点 大于等于 1
【其中去掉后 联通块的数量 也要分情况
如果 是 根节点 就是 满足条件的数量
不是根节点就是加一
】
直接给 poj 1523 的代码
4.割边
这个就是 在割点的情况上 存一个边
5.点双
研究结果是 在栈中存 边
但是还没有写过 题。
暂时 先这么着吧
tarjan 写法 博大精深啊!
脑子不好使 决定 写一写。。
主要决定 写一写双联通分量
先介绍:
1.割点: 如果一个点去掉 图就不再联通 则这个点 为 割点
2.点双联通: 没有 割点 的图
3.边双连通:没有 割边 的图
那 总结一下 所有 的 tajan吧
1.强连通分量:
void tarjan(int x) { low[x]=dfn[x]=++time; instack[x]=1; stack[++top]=x; for(int i=first[x];i!=-1;i=e[i].nxt) { int v=e[i].t; if(!dfn[v]) { tarjan(v); low[x]=min(low[x],low[v]); } else if(instack[v]) { low[x]=min(low[x],dfn[v]); } } if(low[x] == dfn[x]) { ++index; while(1) { int t=stack[top--]; instack[t]=0; belong[t]=index; if(t ==x) break; } } }
2.边双【边双和强连通分量差不了多少 】
唯一的差距大概就是 要统计 一下 编号 来判断 块 当然 无向边 是要判一下 平行边的
void tarjan(int x,int f) { low[x]=dfn[x]=++time; instack[x]=1; stack[++top]=x; for(int i=first[x];i!=-1;i=e[i].nxt) { int v=e[i].t; if(!dfn[v]) { tarjan(v,x); low[x]=min(low[x],low[v]); } else if(v!=f && instack[v]) { low[x]=min(low[x],dfn[v]); } } if(low[x] == dfn[x]) { ++index; while(1) { int t=stack[top--]; instack[t]=0; belong[t]=index; if(t ==x) break; } } } ... for(int i=1;i<=n;i++) { for(int j=first[i];j!=-1;j=e[j].nxt) { int v=e[j].t; if(belong[i]!=belong[v]) { deg[belong[i]]++; } } }
3.割点
割点 主要就是:low[f]>=dfn[v];
如果就是根节点 那么 根节点 的子树 大于1
别的点的话 这样 的点 大于等于 1
【其中去掉后 联通块的数量 也要分情况
如果 是 根节点 就是 满足条件的数量
不是根节点就是加一
】
直接给 poj 1523 的代码
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; //by mars_ch int n; struct data { int f,t; int nxt; }e[1005*1005]; int first[1005]; int dfn[1005],low[1005],sson[1005],instack[1005],vis[1005]; int tot,time,root,top,cnt; void add(int a,int b) { e[++tot].f=a; e[tot].t=b; e[tot].nxt=first[a]; first[a]=tot; } void tarjan(int x) { low[x]=dfn[x]=++time; instack[x]=1; for(int i=first[x];i!=-1;i=e[i].nxt) { int t=e[i].t; if(!dfn[t]) { tarjan(t); low[x]=min(low[x],low[t]); if(low[t]>=dfn[x]) { sson[x]++; } } else { low[x]=min(low[x],dfn[t]); } } } int main() { int a,b,cases=0; while(scanf("%d",&a) && a!=0) { memset(first,-1,sizeof(first)); memset(sson,0,sizeof(sson)); memset(vis,0,sizeof(vis)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); time=0,top=0,tot=0,root=0,cnt=0; bool flag=false; scanf("%d",&b); if(!vis[a]) ++cnt,vis[a]=1; if(!vis[b]) ++cnt,vis[b]=1; add(a,b); add(b,a); while(scanf("%d",&a) && a) { scanf("%d",&b); if(!vis[a]) ++cnt,vis[a]=1; if(!vis[b]) ++cnt,vis[b]=1; add(a,b); add(b,a); } tarjan(1); printf("Network #%d\n",++cases); if(sson[1]>1) flag=true,printf(" SPF node 1 leaves %d subnets\n",sson[1]); for(int i=2;i<=cnt;i++) { //printf("%d %d\n",i,sson[i]); if(sson[i]) { printf(" SPF node %d leaves %d subnets\n",i,sson[i]+1); flag=1; } } if(!flag) printf(" No SPF nodes\n"); puts(""); } return 0; }
4.割边
这个就是 在割点的情况上 存一个边
void tarjan(int u,int f) { int s=0; low[u]=dfn[u]=++time; for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(!dfn[v]) { tarjan(v,u); low[u]=min(low[u],low[v]); if(!(low[v]>dfn[u])) { merge(v,u); } else { br[++brn][0]=u; br[++brn][1]=v; } } else if(v!=f) { low[u]=min(low[u],dfn[v]); } } }
5.点双
研究结果是 在栈中存 边
但是还没有写过 题。
暂时 先这么着吧
tarjan 写法 博大精深啊!
相关文章推荐
- 理解死锁
- POJ 2015 IP Address
- 使用Java7提供的Fork/Join框架
- spi中的write和read的数据传输过程
- array_filter,匿名函数
- KMP算法
- php中关于mysqli和mysql区别的一些知识点分析
- Contact API的结构和使用方法
- COGS1117
- jvm性能调优都做了什么
- 深度学习/神经神经网络常用激活函数总结
- 面试的准备期(一)
- 多线程调试
- UVALive 6604 Airport Sort(逆序对+贪心)
- 图像处理书籍笔记1--基本图像处理运算1
- 每日一JAVA----------JAR命令
- MyBatis数据持久化 SQL复用(可重用的 SQL 代码段)
- MIT 6.00 1x Lecture 3 - Simple Algorithms 简单算法 学习笔记
- 用mysqlbinlog工具查看
- 【bzoj1015】星球大战starwar