tarjan[强连通分量][求割边割点][缩点]
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tarjan[强连通分量][求割边割点][缩点]相关的知识,希望对你有一定的参考价值。
强连通分量:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=100000+15; 5 struct Edge { 6 int x,y,next; 7 Edge(int x=0,int y=0,int next=0): 8 x(x),y(y),next(next) {} 9 } edge[maxn]; 10 int sumedge,head[maxn]; 11 int n,m; 12 int ins(int x,int y) { 13 edge[++sumedge]=Edge(x,y,head[x]); 14 return head[x]=sumedge; 15 } 16 bool instack[maxn]; 17 int top,Stack[maxn]; 18 int dfn[maxn],low[maxn],tim; 19 bool vis[maxn]; 20 int col[maxn],sumcol; 21 int dfs(int now) { 22 dfn[now]=low[now]=++tim; 23 Stack[++top]=now; 24 vis[now]=true; 25 instack[now]=true; 26 for (int u=head[now]; u; u=edge[u].next) 27 if (instack[edge[u].y]) 28 low[now]=min(low[now],dfn[edge[u].y]); 29 else if (!vis[edge[u].y]) { 30 dfs(edge[u].y); 31 low[now]=min(low[now],low[edge[u].y]); 32 } 33 if (low[now]==dfn[now]) { 34 sumcol++; 35 col[now]=sumcol; 36 while (Stack[top]!=now) { 37 col[Stack[top]]=sumcol; 38 instack[Stack[top]]=false; 39 top--; 40 } 41 instack[now]=false; 42 top--; 43 } 44 return 0; 45 } 46 int main() { 47 scanf("%d%d",&n,&m); 48 for (int i=1; i<=m; i++) { 49 int x,y; 50 scanf("%d%d",&x,&y); 51 ins(x,y); 52 } 53 for (int i=1; i<=n; i++) 54 if (!vis[i]) dfs(i); 55 return 0; 56 }
缩点:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=100000+15; 5 struct Edge { 6 int x,y,next; 7 Edge(int x=0,int y=0,int next=0): 8 x(x),y(y),next(next) {} 9 } edge[maxn],edge2[maxn]; 10 map <int, bool > Map[maxn]; 11 int sumedge,head[maxn]; 12 int n,m; 13 int sumedge2,head2[maxn]; 14 int ins2(int x,int y) { 15 edge2[++sumedge2]=Edge(x,y,head2[x]); 16 return head2[x]=sumedge; 17 } 18 int ins(int x,int y) { 19 edge[++sumedge]=Edge(x,y,head[x]); 20 return head[x]=sumedge; 21 } 22 bool instack[maxn]; 23 int top,Stack[maxn]; 24 int dfn[maxn],low[maxn],tim; 25 bool vis[maxn]; 26 int col[maxn],sumcol; 27 int dfs(int now) { 28 dfn[now]=low[now]=++tim; 29 Stack[++top]=now; 30 vis[now]=true; 31 instack[now]=true; 32 for (int u=head[now]; u; u=edge[u].next) 33 if (instack[edge[u].y]) 34 low[now]=min(low[now],dfn[edge[u].y]); 35 else if (!vis[edge[u].y]) { 36 dfs(edge[u].y); 37 low[now]=min(low[now],low[edge[u].y]); 38 } else { 39 } 40 if (low[now]==dfn[now]) { 41 sumcol++; 42 col[now]=sumcol; 43 while (Stack[top]!=now) { 44 col[Stack[top]]=sumcol; 45 instack[Stack[top]]=false; 46 top--; 47 } 48 instack[now]=false; 49 top--; 50 } 51 return 0; 52 } 53 int main() { 54 scanf("%d%d",&n,&m); 55 for (int i=1; i<=m; i++) { 56 int x,y; 57 scanf("%d%d",&x,&y); 58 ins(x,y); 59 } 60 for (int i=1; i<=n; i++) 61 if (!vis[i]) dfs(i); 62 for (int i=1; i<=n; i++) 63 for (int u=head[i]; u; u=edge[u].next) 64 if (col[i]!=col[edge[u].y]) 65 if (Map[col[i]].find(col[edge[u].y])==Map[col[i]].end()) { 66 Map[col[i]][col[edge[u].y]]=true; 67 ins2(col[i],col[edge[u].y]); 68 } 69 return 0; 70 }
求割边割点:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn=100000+15; 5 struct Edge { 6 int x,y,next; 7 Edge(int x=0,int y=0,int next=0): 8 x(x),y(y),next(next) {} 9 } edge[maxn*2]; 10 int sumedge,head[maxn],n,m; 11 int ins(int x,int y) { 12 edge[++sumedge]=Edge(x,y,head[x]); 13 return head[x]=sumedge; 14 } 15 int low[maxn],dfn[maxn],tim; 16 bool vis[maxn]; 17 bool cutedge[maxn],cutpoint[maxn]; 18 int dfs(int now,int pre) { //需要多记录父边的编号 19 dfn[now]=low[now]=++tim; 20 vis[now]=true; 21 int sum=0; //树边数目 22 bool boo=false; 23 for (int u=head[now]; u!=-1; u=edge[u].next) 24 if ((u^1)!=pre) //确定不是父边 25 if (!vis[edge[u].y]) { 26 sum++; 27 dfs(edge[u].y,u); 28 if (low[edge[u].y]>dfn[now]) { //判断割边 29 cutedge[u/2]=true; //u/2为边的实际编号 30 } 31 if (low[edge[u].y]>=dfn[now]) //判断割点 32 boo=true; 33 low[now]=min(low[now],low[edge[u].y]); 34 } else { 35 low[now]=min(low[now],dfn[edge[u].y]); 36 } 37 if (pre==-1) { //分情况判断割点 38 if (sum>1) cutpoint[now]=true; 39 } else { 40 if (boo) cutpoint[now]=true; 41 } 42 return 0; 43 } 44 int main() { 45 scanf("%d%d",&n,&m); 46 sumedge=-1; //使得代表同一条边的两边编号更有关系 47 memset(head,-1,sizeof(head)); 48 for (int i=1; i<=m; i++) { 49 int x,y; 50 scanf("%d%d",&x,&y); 51 ins(x,y); 52 ins(y,x); 53 } 54 for (int i=1; i<=n; i++) 55 if (!vis[i]) dfs(i,-1); 56 for (int i=1; i<=n; i++) 57 if (cutpoint[i]) printf("%d\n",i) ; 58 return 0; 59 }
以上是关于tarjan[强连通分量][求割边割点][缩点]的主要内容,如果未能解决你的问题,请参考以下文章
Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)
Tarjan应用:求割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)