Tarjan模板 求割点数+桥+连通分量数 来自kuangbin
2016-08-09 19:25
507 查看
POJ1144求割点数 求桥的代码也在里面:
求连通分量数:
#include <stdio.h> #include <algorithm> #include <iostream> #include <string.h> using namespace std; /* * 求 无向图的割点和桥 * 可以找出割点和桥,求删掉每个点后增加的连通块。 * 需要注意重边的处理,可以先用矩阵存,再转邻接表,或者进行判重 */ const int MAXN = 10010; const int MAXM = 100010; struct Edge { int to,next; bool cut;//是否为桥的标记 }edge[MAXM]; int head[MAXN],tot; int Low[MAXN],DFN[MAXN],Stack[MAXN]; int Index,top; bool Instack[MAXN]; bool cut[MAXN]; int add_block[MAXN];//删除一个点后增加的连通块 int bridge; void addedge(int u,int v) { edge[tot].to = v;edge[tot].next = head[u];edge[tot].cut = false; head[u] = tot++; } void Tarjan(int u,int pre) { int v; Low[u] = DFN[u] = ++Index; Stack[top++] = u; Instack[u] = true; int son = 0; for(int i = head[u];i != -1;i = edge[i].next) { v = edge[i].to; if(v == pre)continue; if( !DFN[v] ) { son++; Tarjan(v,u); if(Low[u] > Low[v])Low[u] = Low[v]; /* //桥 //一条无向边(u,v)是桥,当且仅当(u,v)为树枝边,且满足DFS(u)<Low(v)。 if(Low[v] > DFN[u]) { bridge++; edge[i].cut = true; edge[i^1].cut = true; }*/ //割点 //一个顶点u是割点,当且仅当满足(1)或(2) (1) u为树根,且u有多于一个子树。 //(2) u不为树根,且满足存在(u,v)为树枝边(或称父子边, //即u为v在搜索树中的父亲),使得DFS(u)<=Low(v) if(u != pre && Low[v] >= DFN[u])//不是树根 { cut[u] = true; add_block[u]++; } } else if( Low[u] > DFN[v]) Low[u] = DFN[v]; } //树根,分支数大于1 if(u == pre && son > 1)cut[u] = true; if(u == pre)add_block[u] = son - 1; Instack[u] = false; top--; } void solve(int N) { memset(DFN,0,sizeof(DFN)); memset(Instack,false,sizeof(Instack)); memset(add_block,0,sizeof(add_block)); memset(cut,false,sizeof(cut)); Index = top = 0; bridge = 0; for(int i = 1;i <= N;i++) if(!DFN[i]) Tarjan(i,i); int ans = 0; for(int i = 1;i <= N;i++) if(cut[i]) ans++; printf("%d\n",ans); } void init() { tot = 0; memset(head,-1,sizeof(head)); } int g[110][110]; char buf[1010]; int main() { int n; while(scanf("%d",&n)==1 && n) { gets(buf); memset(g,0,sizeof(g)); while(gets(buf)) { if(strcmp(buf,"0")==0)break; char *p = strtok(buf," "); int u; sscanf(p,"%d",&u); p = strtok(NULL," "); int v; while(p) { sscanf(p,"%d",&v); p = strtok(NULL," "); g[u][v]=g[v][u]=1; } } init(); for(int i = 1;i <= n;i++) for(int j = i+1;j <= n;j++) if(g[i][j]) { addedge(i,j); addedge(j,i); } solve(n); } return 0; }
求连通分量数:
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; const int MAXN = 110; const int MAXM = 110*110; struct Edge { int to,next; }edge[MAXM]; int head[MAXN],tot; int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN]; int Index,top; int scc; bool Instack[MAXN]; void addedge(int u,int v) { edge[tot].to = v;edge[tot].next = head[u];head[u] = tot++; } void Tarjan(int u) { int v; Low[u] = DFN[u] = ++Index; Stack[top++] = u; Instack[u] = true; for(int i = head[u];i != -1;i = edge[i].next) { v = edge[i].to; if(!DFN[v]) { Tarjan(v); if(Low[u] > Low[v]) Low[u] = Low[v]; } else if(Instack[v] && Low[u] > DFN[v]) Low[u] = DFN[v]; } if(Low[u] == DFN[u]) { scc++; do { v = Stack[--top]; Belong[v] = scc; Instack[v] = false; } while( v!= u); } } int in[MAXN],out[MAXN]; void solve(int dfa9 N) { memset(DFN,0,sizeof(DFN)); memset(Instack,false,sizeof(Instack)); Index = scc = top = 0; for(int i = 1;i <= N;i++) if(!DFN[i]) Tarjan(i); if(scc == 1) { printf("1\n0\n"); return; } for(int i = 1;i <= scc;i++) in[i] = out[i] = 0; for(int u = 1;u <= N;u++) { for(int i = head[u];i != -1;i = edge[i].next) { int v = edge[i].to; if(Belong[u] != Belong[v]) { in[Belong[v]]++; out[Belong[u]]++; } } } int ans1=0,ans2=0; for(int i = 1;i <= scc;i++) { if(in[i]==0)ans1++; if(out[i]==0)ans2++; } printf("%d\n%d\n",ans1,max(ans1,ans2)); } void init() { tot = 0; memset(head,-1,sizeof(head)); } int main() { int n; int v; while(scanf("%d",&n) == 1) { init(); for(int i = 1;i <= n;i++) { while(scanf("%d",&v)==1 && v) { addedge(i,v); } } solve(n); } return 0; }
相关文章推荐
- 有向图强连通分量Tarjan模板
- 【模板】【强连通分量】【Tarjan】
- tarjan 算法模板(边连通分量)
- 强连通分量Kosaraju、Tarjan【模板】
- tyvj 1111 舞会 有向图强连通分量 Kosaraju模板 tarjan模板
- HDU 1269 迷宫城堡【Tarjan强连通分量 模板】
- hdu 1269 Tarjan强连通分量 模板
- 【模板】Tarjan求强连通分量
- hdu1269 Tarjan强连通分量 模板
- 强连通分量Tarjan模板
- [POJ 3180] The Cow Prom Tarjan求强连通分量 模板题
- 连通分量模板:tarjan: 求割点 && 桥 && 缩点 && 强连通分量 && 双连通分量 && LCA(近期公共祖先)
- tarjan 边连通分量+2-sat 模板
- hdu1269迷宫城堡(tarjan求强连通分量模板)
- 二分图强连通分量 tarjan 模板
- hdu1269 Tarjan强连通分量 模板(转)
- 连通分量模板:tarjan: 求割点 && 桥 && 缩点 && 强连通分量 && 双连通分量 && LCA(最近公共祖先)
- 有向图的强连通分量的求解算法Tarjan
- 4612 warm up tarjan+bfs求树的直径(重边的强连通通分量)忘了写了,今天总结想起来了。
- Network of Schools POJ - 1236 tarjan强连通分量